Updating attributes of existing features


Summary
This topic describes the various ways to update feature attributes and the considerations to be aware of while doing so.


Attribute updates

Attributes are usually updated on a per feature and field basis using IFeature.Value. The Value property takes the field index as an integer parameter, which can also be supplied by finding the particular field with a text string. Once the desired values are set for the particular feature, the values are stored using IFeature.Store. Setting attribute values on features, like most other editing workflows, should be contained within an edit operation.
Field type and size are not validated when you use the Value property to update attribute values. You can check field types and other properties, such as if the field is read-only, through the IField interface. If you are not familiar with the data source you're working with, put the appropriate checks in before setting values on a field.
The following code shows the use of IFeature.Value:
[C#]
m_Editor.StartOperation();
feature.Value(feature.Fields.FindField("LotNumberField")) = m_lotNum;
feature.Value(4) = 92373;
feature.Store();
m_Editor.StopOperation("Attribute update");
[VB.NET]
m_Editor.StartOperation()
feature.Value(feature.Fields.FindField("LotNumberField")) = m_lotNum
feature.Value(4) = 92373
feature.Store()
m_Editor.StopOperation("Attribute update")

Updating attributes with subtypes

If you change the value of a subtype field, change the default values in the other fields applicable to that new subtype as well. Default values can be set using the IRowSubtypes interface as shown in the following code:
[C#]
IRowSubtypes rowSubtypes = feature as IRowSubtypes;
if (rowSubtypes != null)
{
    // Set the subtype.
    rowSubtypes.SubtypeCode = IEditLayers.CurrentSubtype; //or a valid subtype code
    // Initialize default values for the subtype.
    rowSubtypes.InitDefaultValues();
    feature.Store();
}
[VB.NET]
Dim rowSubtypes As IRowSubtypes = feature
If Not rowSubtypes Is Nothing Then
    'Set the subtype.
    rowSubtypes.SubtypeCode = IEditLayers.CurrentSubtype 'or a valid subtype code
    'Initialize default values for the subtype.
    rowSubtypes.InitDefaultValues()
    feature.Store()
End If

Updating attributes of a set of features

Many editing workflows require that you update the attributes of more than one feature at a time. For example, updating the values returned by features from a spatial or attribute query or applying a value to the selected set of features that the user has chosen interactively. These scenarios are discussed in this section.

Working with cursors

A cursor is a data access object that can be used to iterate over a set of rows in a table or to insert new rows into a table. For more information on cursors, see Query classes and cursors. In the context of updating the attributes of existing features, you can use a search cursor or an update cursor. These cursors are returned by the corresponding method (Search or Update) from the ITable or IFeatureClass interface. Both take a query filter as input that can be used to restrict the set of rows returned.
Although both types can be used to update attributes, use search cursors rather than update cursors in ArcGIS for Desktop because search cursors take advantage of the map cache and can be more efficient. Update cursors read directly from the database each time a row is read and are more suited to ArcGIS Engine applications when working with complex features.
Feature attributes are updated using the same methods as described above when using cursors, but the row is committed differently depending on the type of cursor used. Search cursors use the Store method, while update cursors use the UpdateFeature method. Do not call IFeature.Store on update cursors.
The following code shows how to use a search cursor to iterate through and update polygons that fall within a point in a point collection:
[C#]
m_editor.StartOperation();
//Loop through midpoints, select polygon, and calculate.
for (int i = 0; i < midPoints.PointCount; i++)
{
    IPoint midPoint = midPoints.get_Point(i);
    spatialFilter = new SpatialFilterClass();
    spatialFilter.Geometry = midPoint;
    spatialFilter.GeometryField =
        m_editLayers.CurrentLayer.FeatureClass.ShapeFieldName;
    spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelWithin;
    SearchCursor = featLayer.Search(spatialFilter, true);
    while ((feature = SearchCursor.NextFeature()) != null)
    {
        feature.set_Value(feature.Fields.FindField(cmbPINField.Text), m_lotNum);
        feature.Store();
        m_lotNum += int.Parse(txtlotinc.Text);
    }
}

m_editor.StopOperation("Polygon Update");
[VB.NET]
m_editor.StartOperation()
'Loop through midpoints, select polygon, and calculate.
For i As Integer = 0 To midPoints.PointCount - 1
    Dim midPoint As IPoint = midPoints.Point(i)
    spatialFilter = New SpatialFilterClass()
    spatialFilter.Geometry = midPoint
    spatialFilter.GeometryField = m_editLayers.CurrentLayer.FeatureClass.ShapeFieldName
    spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelWithin
    SearchCursor = featLayer.Search(spatialFilter, True)
    feature = SearchCursor.NextFeature()
    Do While feature IsNot Nothing
        feature.Value(feature.Fields.FindField(cmbPINField.Text)) = m_lotNum
        feature.Store()
        m_lotNum + = Integer.Parse(txtlotinc.Text)
        feature = SearchCursor.NextFeature()
    Loop
Next i
m_editor.StopOperation("Polygon Update")
In the following code example, an update cursor is used to change the value of the Type field to Toll Highway in a feature class of roads, where the name of the road is Highway 104:
[C#]
public void UseUpdateCursor(IFeatureClass featureClass)
{
    // Restrict the number of features to be updated.
    IQueryFilter queryFilter = new QueryFilterClass();
    queryFilter.WhereClause = "NAME = 'Highway 104'";
    queryFilter.SubFields = "TYPE";

    // Use IFeatureClass.Update to populate IFeatureCursor.
    IFeatureCursor updateCursor = featureClass.Update(queryFilter, false);

    int typeFieldIndex = featureClass.FindField("TYPE");
    IFeature feature = null;
    try
    {
        while ((feature = updateCursor.NextFeature()) != null)
        {
            feature.set_Value(typeFieldIndex, "Toll Highway");
            updateCursor.UpdateFeature(feature);
        }
    }
    catch (COMException comExc)
    {
        // Handle any errors that might occur on NextFeature().
    }

    // If the cursor is no longer needed, release it.
    Marshal.ReleaseComObject(updateCursor);
}
[VB.NET]
Public Sub UseUpdateCursor(ByVal featureClass As IFeatureClass)
    
    ' Restrict the number of features to be updated.
    Dim queryFilter As IQueryFilter = New QueryFilterClass()
    queryFilter.WhereClause = "NAME = 'Highway 104'"
    queryFilter.SubFields = "TYPE"
    
    ' Use IFeatureClass.Update to populate IFeatureCursor.
    Dim updateCursor As IFeatureCursor = featureClass.Update(queryFilter, False)
    Dim typeFieldIndex As Integer = featureClass.FindField("TYPE")
    
    Try
    Dim feature As IFeature = updateCursor.NextFeature()
    Do While Not feature Is Nothing
        feature.Value(typeFieldIndex) = "Toll Highway"
        updateCursor.UpdateFeature(feature)
        feature = updateCursor.NextFeature()
    Loop
    Catch comExc As COMException
    ' Handle any errors that might occur on NextFeature().
    End Try
    
    ' If the cursor is no longer needed, release it.
    Marshal.ReleaseComObject(updateCursor)
    
End Sub

Working with edit selections

You can reference the set of selected features through the editor via IEditor.EditSelection, returning an enumeration of features, IEnumFeature. As with cursors, you can iterate through this collection and calculate the attributes on individual features. However, the selection can contain features from more than one layer, and you should take measures to handle this possibility.

Validating feature attributes

The editor does not automatically check the value you supply for a field against domain ranges, subtypes, or other integrity rules, such as geometric networks and relationships. You can use the IValidate.Validate method to validate features. See Validating features for more information on using this method.

Updating attributes outside edit sessions

In some cases, using an edit session can have an unnecessarily adverse effect on performance. The primary example of this is when a dataset has been created and a large number of inserts and attribute updates are being performed. Using an edit session in this case can hinder performance, and the option of rolling back changes is not applicable since the dataset can simply be deleted, recreated, and repopulated in the event of errors. When bulk inserts are being performed on a dataset with existing rows, using an edit session can still be the best option.
Outside an edit session, explicitly start and stop transactions using the ITransactions interface. If rows are updated or inserted outside an edit session or transaction and failure occurs, you cannot recover or rollback the operation.
 
Nested transactions are not supported. Attempting to start a transaction when a transaction has already been started does nothing.
Transactions do not support the updating of complex features such as geometric networks, topologies, and terrains.
The following code example shows how to execute updates or inserts outside an edit operation using the ITransactions interface:
[C#]
public void EditsOutsideAnEditSession(IWorkspace workspace)
{
    // Cast the workspace to the IWorkspaceEdit2 interface to confirm whether the workspace
    // is in an edit operation. If so, raise an exception.
    IWorkspaceEdit2 workspaceEdit2 = (IWorkspaceEdit2)workspace;
    if (workspaceEdit2.IsInEditOperation)
    {
        throw new Exception("Cannot use ITransactions during an edit operation.");
    }
    // Begin a transaction.
    ITransactions transactions = (ITransactions)workspace;
    transactions.StartTransaction();
    try
    {
        // Perform updates and inserts here.
        // If the updates and inserts are successful, commit the changes.
        transactions.CommitTransaction();
    }
    catch (COMException comExc)
    {
        // If an error occurs during the inserts and updates, rollback the transaction.
        transactions.AbortTransaction();
    }
}
[VB.NET]
Public Sub EditsOutsideAnEditSession(ByVal workspace As IWorkspace)
    ' Cast the workspace to the IWorkspaceEdit2 interface to confirm whether the workspace
    ' is in an edit operation. If so, raise an exception.
    Dim workspaceEdit2 As IWorkspaceEdit2 = CType(workspace, IWorkspaceEdit2)
    If workspaceEdit2.IsInEditOperation Then
        Throw New Exception("Cannot use ITransactions during an edit operation.")
    End If
    
    ' Begin a transaction.
    Dim transactions As ITransactions = CType(workspace, ITransactions)
    transactions.StartTransaction()
    Try
    ' Perform updates and inserts here.
    
    ' If the updates and inserts are successful, commit the changes.
    transactions.CommitTransaction()
    Catch comExc As COMException
    ' If an error occurs during the inserts and updates, rollback the transaction.
    transactions.AbortTransaction()
    End Try
End Sub

Updating attributes using SQL

It is possible to edit the data in a geodatabase using SQL outside the ArcGIS framework. However, before doing so it is important to understand the geodatabase data model that has been implemented. Are there any advanced geodatabase objects present, such as geometric networks or topologies? If so, which feature classes are involved?
When working with a geodatabase using ArcGIS applications, the behavior and validation rules that the geodatabase enforces will automatically manage the relationships between those feature classes. For example, when a composite relationship is established between two objects, as in the case of feature-linked annotation, any modifications made to those objects using ArcGIS applications and the geodatabase application programming interface (API) will ensure the relationship between the features and the annotation is always maintained. This implicit geodatabase behavior does not occur if SQL is used to directly modify the data.
However, for performance reasons, there may be occasions when modifying the data in a geodatabase is best done using SQL rather than the geodatabase API, as in the case of bulk attribute updates or data loading operations. If the target geodatabase table attributes play no part in geodatabase behavioral constraints or data validation rules, then updating geodatabase tables using SQL can be an efficient approach to modifying the data. However, because an edit operation undertaken using SQL will bypass these geodatabase constraints and data integrity rules and will not respect the relationships between feature classes, the potential impact of such an operation should be considered carefully prior to making any changes. It is important to ensure that modifying certain table attributes will not affect other objects in the geodatabase.
The following guidelines apply to the use of SQL for modifying information in a geodatabase:
  • Avoid updating records using SQL after the data has been versioned, unless SQL is used in conjunction with an ArcSDE multiversioned view. This applies to ArcSDE geodatabases only—personal geodatabases do not support versioning.
  • Always issue a commit or rollback statement after the SQL statement has been executed in the database to ensure the changes are either made permanent or undone as required. Failing to do so can cause problems for the database management system (DBMS). For example, a database compress operation will wait for uncommitted DBMS DML statements to be committed before executing successfully.
  • When updating unversioned data using SQL, avoid modifying any attributes that, through geodatabase behavior, affect other objects in the database—as in the case of feature-linked annotation and relationship classes.
  • Avoid using SQL to modify the geometries of feature classes that participate in any advanced geodatabase objects or functionality such as geometric networks, topologies, and relationships. Modifications to feature classes participating in networks, topologies, annotation, dimension, or relationship classes should be restricted to ArcGIS for Desktop applications and the geodatabase API. Third party SQL-based applications can read the data, but any modifications they make to the data will not be reflected in the network, topology, or relationship.
  • Never update the Row_ID (ObjectID) field with SQL—this field is allocated and managed by the geodatabase and should not be altered.






Development licensing Deployment licensing
ArcGIS for Desktop Basic ArcGIS for Desktop Basic
ArcGIS for Desktop Standard ArcGIS for Desktop Standard
ArcGIS for Desktop Advanced ArcGIS for Desktop Advanced