How to obtain changes made in the current edit session


Summary
This article shows how to discover the changes made to a class in the current edit session or current edit operation.

In this topic


Obtaining changes made in the current edit session

It is possible to obtain the changes made in an edit session using the get_EditDataChanges() method on the IWorkspaceEdit2 interface. The data changes objects and exposes the ability to obtain the data changes in the current edit session or current edit operation. This article shows how and when to use these objects to discover changes.
An edit session must be active to get the data changes from within the edit session. The first step is to establish a reference to the IDataChangesEx interface. This is done by casting from the IWorkspaceEdit object that was used to start the edit session.
Next, specify the scope for which you want the differences returned; the scope can either be in the edit session or the edit operation. Once the scope has been defined, the ModifiedClasses property is used to get an enumeration of all the changed classes. See the following code example:
[Java]
static IEnumBSTR getModifiedClasses(IWorkspace workspace)throws Exception{
    IWorkspaceEdit2 workspaceEdit2 = (IWorkspaceEdit2)workspace;
    int scope = esriEditDataChangesType.esriEditDataChangesWithinSession;
    IDataChangesEx dataChanges = workspaceEdit2.getEditDataChanges(scope);
    return dataChanges.getModifiedClasses();
}
It is important to note that the data changes are only current when EditDataChanges is called. This means that any edits made after this call will not be reflected in calls to the members of the IDataChangesEx interface.
Looping through changed classes
Looping through the changed classes, the IDifferenceCursorEx interface can be used to obtain specific differences. You can obtain a set of feature IDs of all the changed features or get a difference cursor of changed features. The following code example shows how to retrieve a set of IDs containing all of the inserted and deleted features:
[Java]
// For example, className = "customers"
static IFIDSet InsertedAndDeletedIDs(IDataChangesEx dataChangesEx, String className)
    throws Exception{
    // Get the IDs of inserted rows
    IFIDSet insertFidSet = dataChangesEx.getChangedIDs(className,
        esriDifferenceType.esriDifferenceTypeInsert);
    // Get the IDs of deleted rows
    IFIDSet deleteNoChangeFidSet = dataChangesEx.getChangedIDs(className,
        esriDifferenceType.esriDifferenceTypeDeleteNoChange);
    // Join the two ID sets and return the result.
    IFIDSetOperator fidSetOperator = (IFIDSetOperator)insertFidSet;
    return fidSetOperator.union(deleteNoChangeFidSet);
}
Using the difference cursor in a loop
The difference cursor can be used in a loop to obtain specific information about the changed features. This is very powerful because the ExtractEx() method allows you to obtain references to the row objects before and after the changes are made. See the following code example:
If it isn't known whether or not changes of a particular type have been made, calls to the IDataChangesEx.ExtractEx method should be within a try/catch block.  If a type of change is specified where no changes of that type have actually been made, a COMException will be thrown.  For example, if an attempt is made to create a difference cursor of updates when only inserts and deletions have occurred, an exception will be thrown.  For readability, however, the two following code examples do not follow this practice.
[Java]
static void displayModifiedValues(IDataChangesEx dataChangesEx, String className)
    throws Exception{
    // Get a cursor over the updated rows.
    IDifferenceCursorEx differenceCursorEx = dataChangesEx.extractEx(className,
        esriDifferenceType.esriDifferenceTypeUpdateNoChange);
    // Prepare the output parameters.
    int[] featureID = {
         - 1
    };
    IRow[] sourceRow = new IRow[1];
    IRow[] differenceRow = new IRow[1];
    ILongArray[] fieldIndexes = new ILongArray[1];
    // Iterate through the cursor.
    differenceCursorEx.next(featureID, sourceRow, differenceRow, fieldIndexes);
    while (featureID[0] !=  - 1){
        System.out.println("Changes for feature " + featureID[0]);
        // Go to each changed field and display the old and new values.
        for (int i = 0; i < fieldIndexes[0].getCount(); i++){
            System.out.println("Previous value: " + sourceRow[0].getValue(i));
            System.out.println("Current value: " + differenceRow[0].getValue(i));
        }
        differenceCursorEx.next(featureID, sourceRow, differenceRow, fieldIndexes);
    }
}
Complete code example
A complete code example using these objects is provided as follows. The code outputs all changes that occurred in the defined scope:
[Java]
//scope is defined by constants in esriEditDataChangesType 
static void showChangesForScope(IWorkspace workspace, int scope)throws Exception{
    IWorkspaceEdit2 workspaceEdit2 = (IWorkspaceEdit2)workspace;
    IDataChangesEx dataChangesEx = workspaceEdit2.getEditDataChanges(scope);

    // Show the changes for each modified class in the workspace.
    IEnumBSTR modifiedClasses = dataChangesEx.getModifiedClasses();
    String modifiedClass = null;
    while ((modifiedClass = modifiedClasses.next()) != null){
        IDifferenceCursorEx differenceCursorEx = dataChangesEx.extractEx
            (modifiedClass, esriDifferenceType.esriDifferenceTypeUpdateNoChange);
        int[] featureID = {
             - 1
        };
        IRow[] sourceRow = new IRow[1];
        IRow[] differenceRow = new IRow[1];
        ILongArray[] fieldIndexes = new ILongArray[1];
        // Get the row values and featureOID.
        differenceCursorEx.next(featureID, sourceRow, differenceRow, fieldIndexes);
        System.out.println("Updates for class " + modifiedClass);
        while (featureID[0] !=  - 1){
            System.out.println("Feature OID: " + featureID[0]);
            // Display each changed field value.
            for (int i = 0; i < fieldIndexes[0].getCount(); i++){
                System.out.println("Was: " + differenceRow[0].getValue
                    (fieldIndexes[0].getElement(i)) + " Is Now: " +
                    sourceRow[0].getValue(fieldIndexes[0].getElement(i)));
            }
            System.out.println();
            differenceCursorEx.next(featureID, sourceRow, differenceRow,
                fieldIndexes);
        }
        // Get a FID set for all of the deleted features.
        IFIDSet2 deletedFIDSet = (IFIDSet2)dataChangesEx.getChangedIDs(modifiedClass,
            esriDifferenceType.esriDifferenceTypeDeleteNoChange);
        IEnumIDs deletedEnumIDs = deletedFIDSet.getIDs();
        int nextDeletedID =  - 1;
        while ((nextDeletedID = deletedEnumIDs.next()) !=  - 1){
            System.out.println("Deleted FID: " + nextDeletedID);
        }
        // Get a FID set for all of the inserted features.
        IFIDSet2 insertedFIDSet = (IFIDSet2)dataChangesEx.getChangedIDs
            (modifiedClass, esriDifferenceType.esriDifferenceTypeInsert);
        IEnumIDs insertedEnumIDs = insertedFIDSet.getIDs();
        int nextInsertedID =  - 1;
        while ((nextInsertedID = insertedEnumIDs.next()) !=  - 1){
            System.out.println("Inserted FID: " + nextInsertedID);
        }
    }
}
Extending the code
The code can be easily extended to include other changes over different scopes. One possible way to use this functionality is to call the code when the editing events BeforeStopEditing and BeforeStopOperation are fired.






Development licensingDeployment licensing
ArcGIS for Desktop BasicArcGIS for Desktop Basic
ArcGIS for Desktop StandardArcGIS for Desktop Standard
ArcGIS for Desktop AdvancedArcGIS for Desktop Advanced
Engine Developer KitEngine