I want to add a new field to my featureclass.My code for that is:
public IMxDocument mxDoc;
public IMap map;
IFieldEdit2 field = new FieldClass() as IFieldEdit2;
field.Name_2 = "Parcel_Way";
field.Type_2 = esriFieldType.esriFieldTypeString;
field.Length_2 = 50;
field.DefaultValue_2 = "Parcel";
IFeatureLayer2 flayer=map.Layer[cmboxLayer2.SelectedIndex] as IFeatureLayer2;
IFeatureClass featureclass = flayer.FeatureClass;
try
{
featureclass.AddField(field);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, ex.Source);
throw;
}
Program return this error : enter image description here
What do i neglecting ?
3 Answers 3
Adding a field directly in ArcMap may not work if the feature class is included in your mxd.
Usually, before modifying a feature class schema(such as adding a field), you should acquire an exclusive schema lock, to ensure that the feature class is opened only by your code.
Here's an example acquiring a schema lock
// Try to acquire an exclusive schema lock.
ISchemaLock schemaLock = (ISchemaLock)yourFeatureClass;
try
{
schemaLock.ChangeSchemaLock(esriSchemaLock.esriExclusiveSchemaLock);
// Add your field.
...
}
catch (COMException comExc)
{
// Handle the exception appropriately for the application.
}
finally
{
// Demote the exclusive lock to a shared lock.
schemaLock.ChangeSchemaLock(esriSchemaLock.esriSharedSchemaLock);
}
In your case, probably that you won't be able to acquire a lock because the feature class you want to lock is already opened in your mxd document.
ArcCatalog may be a better place to add this kind of code.
-
Thanks dear Goldrak. But i need to work in arcMapMahdi Ahmadi– Mahdi Ahmadi2014年08月16日 15:02:33 +00:00Commented Aug 16, 2014 at 15:02
-
This code worked.But for second time cant to add another field and i cant delete any field from featureclass too. :(Mahdi Ahmadi– Mahdi Ahmadi2014年08月16日 15:16:53 +00:00Commented Aug 16, 2014 at 15:16
-
Acquiring a schema lock is a good idea, but you still need to test if it has one. Add a boolean like HaveExclusive initialized to false and set it to true after getting the exclusive schema lock then before attempting to add the field check the HaveExclusive value. The way this stands the code will run through whether or not you get a schema lock, you will only be able to add or remove fields if you have exclusive schema lock.Michael Stimson– Michael Stimson2014年08月17日 21:36:45 +00:00Commented Aug 17, 2014 at 21:36
-
Correct me if I'm wrong, but if the schema lock acquisition, it will fall on the COMException catch block, so you can handle the failure. I believe this code is the good way to do it, I took it from an ArcGIS sample codeGoldorak84– Goldorak842014年08月19日 12:13:38 +00:00Commented Aug 19, 2014 at 12:13
-
@MahdiAhmadi If the second time you add a field, you encounter the same error as before, as michealMilesStimson suggested, consider calling Marshal.ReleaseComObject(featureClass); when you're done with your FeatureClassGoldorak84– Goldorak842014年08月19日 12:19:39 +00:00Commented Aug 19, 2014 at 12:19
IFeatureClass.AddField expects a field object, in this case you are providing a IFieldEdit object - thus the type mismatch and error.
Try it this way:
public IMxDocument mxDoc;
public IMap map;
IField NewField = new FieldClass();
IFieldEdit2 field = (IFieldEdit2)NewField;
field.Name_2 = "Parcel_Way";
field.Type_2 = esriFieldType.esriFieldTypeString;
field.Length_2 = 50;
field.DefaultValue_2 = "Parcel";
IFeatureLayer2 flayer=map.Layer[cmboxLayer2.SelectedIndex] as IFeatureLayer2;
IFeatureClass featureclass = flayer.FeatureClass;
try
{
featureclass.AddField(NewField);
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show(ex.Message, ex.Source);
throw;
}
The difference is that I create an IField as new FieldClass() and then modify that field using the IFieldEdit2 interface; IFields themselves cannot be modified directly and need to be cast to an IFieldEdit to modify them, then the new field can be added using the AddField method. The IFieldEdit needs to reference an IField, by casting it directly using IFieldEdit2 field = new FieldClass() as IFieldEdit2;
does that but the IField itself is not linked to anything.
-
Even if he uses an IFieldEdit2 Interface pointer, the underlying COM object is still a FieldClass. Then he passes his IFieldEdit2 object to the AddField method, there will be an implicit cast to IField interface. The problem is probably because he can't acquire schema lock, because the feature class is opened in ArcMapGoldorak84– Goldorak842014年08月15日 15:35:41 +00:00Commented Aug 15, 2014 at 15:35
-
Yeah, I can't to add field with this cod too. This code return same error too. I am agree with Goldorak84 and i think problem is probably because of that layer is open and in use with arcMap.Mahdi Ahmadi– Mahdi Ahmadi2014年08月16日 14:52:44 +00:00Commented Aug 16, 2014 at 14:52
-
1Consider your locking situations, you can lock a feature class by having it open in multiple instances of ArcMap/Catalog or locked by a cursor/feature buffer. Catalog will sometimes continue a lock if you have looked inside the database and then moved on without exiting. If you have any cursors on the feature class you will need to remove them using ReleaseComObject msdn.microsoft.com/en-us/library/…Michael Stimson– Michael Stimson2014年08月17日 21:41:05 +00:00Commented Aug 17, 2014 at 21:41
You can also use the GeoProcessor to add a field.
Function AddField(ByVal TableName As Object, ByVal FieldName As String, ByVal Type As String, Optional ByVal Precision As Integer = 0, Optional ByVal Scale As Integer = 0, Optional ByVal Length As Integer = 0) As Boolean
Dim NewField As ESRI.ArcGIS.DataManagementTools.AddField = New ESRI.ArcGIS.DataManagementTools.AddField
Dim Result As ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2
Dim GP = New ESRI.ArcGIS.Geoprocessor.Geoprocessor
Try
Using releaser As New ESRI.ArcGIS.ADF.ComReleaser
releaser.ManageLifetime(NewField)
NewField.in_table = TableName
NewField.field_name = FieldName
NewField.field_type = Type
If Precision <> 0 Then NewField.field_precision = Precision
If Scale <> 0 Then NewField.field_scale = Scale
If Length <> 0 Then NewField.field_length = Length
Result = CType(GP.Execute(NewField, Nothing), ESRI.ArcGIS.Geoprocessing.IGeoProcessorResult2)
End Using
If Result Is Nothing Then Return False
Return True
Catch ex As Exception
Return False
End Try
End Function
In response to Goldorak84's comment, I tested this with a feature class in an mxd using the following code.
Dim pLayer As ESRI.ArcGIS.Carto.ILayer2 = My.ArcMap.Document.FocusMap.Layer(0)
Dim pFLayer As New ESRI.ArcGIS.Carto.FeatureLayer
pFLayer = pLayer
AddField(pFLayer, "Test", "TEXT", 0, 0, 10)
The field was added to the feature class as expected.
-
If the feature class is already open, like in his code example, it won't work, he will have the same error has he does in his exampleGoldorak84– Goldorak842014年08月15日 18:56:10 +00:00Commented Aug 15, 2014 at 18:56
-
See my addition to the post above. It works as expected.kenbuja– kenbuja2014年08月15日 19:23:36 +00:00Commented Aug 15, 2014 at 19:23