ArcFM Desktop Overview > Technical White Papers > Autoupdater Framework |
This technical white paper provides an overview of the internals of the ArcFM Autoupdater framework. It is written for business partners, clients, or other parties interested in learning more about how autoupdaters work. This document assumes that the reader is familiar with the use and creation of autoupdaters, as described in the ArcFM Solution documentation.
An understanding of the ArcObjects edit events framework is necessary before learning how ArcFM leverages this framework.
ArcObjects provides three kinds of editing events: row events, class events, and editor events.
2.1 RowEvents
Row events, the first set of editing events that gets fired, are not actually events at all. When a row object is edited, the object checks itself to see if it implements the IRowEvents or IFeatureEvents interfaces. If the interface exists, the appropriate routine on those interfaces is called.
For example, if a row is updated by a call to IRow::Store(), the implementation of Store() will call IRowEvents::OnChanged(), if this row implements the IRowEvents interface.
The IRowEvents interface is implemented by creating a "custom GeoObject" that uses COM aggregation to wrap the appropriate Esri object. ArcFM objects are implemented as custom GeoObjects.
![]() |
More recent Esri literature refers to "custom GeoObjects" as "custom features." |
This table explains the Esri method calls that generate calls to row "events":
Esri Edit Method
Row Event
ITable::CreateRow
IFeatureClass::CreateFeature
IRowEvents::OnNew
IRow::Store
IRowEvents::OnChanged
IRow::Delete
IRowEvents::OnDelete
IFeatureEdit::Split
IFeatureEvents::OnSplit
![]() |
Remember, of course, that many other Esri calls resolve down to a call to one of these routines. |
Note that these row event calls are made during the call to the corresponding Esri edit method. The call has not finished, and returning an error code from the row event will cause the caller to fail with the same error code.
There are other row events in addition to the ones described above. IRowEvents::OnInitialize(), IRowEvents::OnValidate(), and IFeatureEvents::InitShape() are not used by the ArcFM Autoupdater framework. IRowEvents::OnMerge() is not implemented by Esri.
2.2 Object Class Events
The second type of editing events supported by ArcObjects are object class events. These are true events, and are described below:
Esri Edit Method
Object Class Event
ITable::CreateRow
IFeatureClass::CreateFeature
IObjectClassEvents::OnCreate
IRow::Store
IObjectClassEvents::OnChange
As with row events, these object class event calls are made during the call to the corresponding Esri edit method. The call has not finished, and returning an error code from the class event will cause the caller to fail with the same error code.
There are two ways to respond to object class events. The easiest way is to implement a custom class extension. This is not required, however. It is also possible to listen to object class events directly. ArcObjects even includes an ObjectClassEvents helper class to make this possible with Visual Basic. One notable component that listens to ObjectClassEvents is the Esri Object Editor extension, which is described in more detail below. It is worth noting that if multiple clients listen to ObjectClassEvents, the order that these clients receive these events is indeterminate.
![]() |
A close look at the Geodatabase Object Model will reveal more interfaces on class extensions, namely IRelatedObjectClassEvents, IRelatedObjectClassEvents2, and IConfirmSendRealtedObjectEvents. Depending on how your relationship classes are configured in ArcCatalog, these can generate additional events. ArcFM does not currently use these interfaces. |
2.3 EditorEvents
Finally, there is a third kind of editing event supported by ArcObjects. These are also true events, generated by the Esri Object Editor class extension. These are typically implemented by creating an Editor extension (an object that supports IExtension and is registered in the “Esri Editor Extensions” COM category).
Esri Edit Method
Editor Event
ITable::CreateRow
IFeatureClass:CreateFeature
IEditEvents::OnCreateFeature
IRow::Store
IEditEvents::OnChangeFeature
IRow::Delete
IEditEvents::OnDeleteFeature
Unfortunately, due to a bug in ArcObjects, returning an error code from the class event will not cause the caller to fail (the error code is not being propagated correctly). The effect of this is that you cannot cause the edit to fail while processing an Editor event.
It is worth noting that Editor Events are really just Object Class Events, repropagated by the Esri Object Editor. Obviously, this means that editor events require the Esri Object Editor, which in turn requires ArcMap. This means that an ArcObjects application that does not require ArcMap will not generate editor events. This kind of application, although possible now, will become far more prevalent with ArcGIS Engine 9.0 and ArcGIS Server 9.0.
It is worth noting, that if multiple clients listen to Editor events, the order that these clients receive these events is indeterminate.
2.4 Esri Event Summary
Here is a summary of the different events that are fired by ArcObjects, and the order in which they occur.
The Autoupdater is 2 in a COM object called MMAutoUpdater. This object is both a COM singleton and an ArcMap Editor extension.
Autoupdaters work differently, depending on whether ArcFM or Esri objects are used.
![]() |
From the perspective of the Autoupdater framework, ArcFM and Designer objects work the same way. All references to “ArcFM Objects” in this document apply equally to Designer objects. |
3.1 Row Events and the Autoupdater
Our ArcFM objects "listen" to Row events by implementing the IRowEvents and IFeatureEvents interfaces, as described in section 2.1 above. In response to these events, methods are called on the MMAutoUpdater object. These methods fire the assigned autoupdaters, as described in section 3.3.
Note that because our ArcFM objects initiate the Autoupdater call, autoupdaters will always fire, even if ArcMap is not running. Because they are called with Row events, returning an error code can prevent the edit from taking place.
3.2 Editor Events and the Autoupdater
In addition to Row Events, the MMAutoUpdater object listens to Editor events, as described in section 2.3 above. If the MMAutoUpdater receives an editor event that involves an ArcFM object, it disregards it, since it will have already received an appropriate Row event. However, if the MMAutoUpdater receives an editor event regarding an Esri object, we fire the assigned autoupdaters as described in section 3.3.
Remember that Editor Events cannot prevent the edit from taking place. The practical effect of this is that returning MM_E_CANCELEDIT has no effect with Esri objects.
3.3 Firing Autoupdaters
When the Autoupdater is fired, Attribute autoupdaters are fired first. These are fired in the order that the fields are listed in the ArcFM Properties for that feature class. If all of these autoupdaters succeed, the Special autoupdaters are fired.
What about edits to Relationships? The answer, of course, is another kind of event, a relationship class event.
Esri Edit Method
Relationship Class Event
IRelationshipClass::CreateRelationship
IRelationshipClassEvents::OnCreate
IRow::Store
IRelationshipClassEvents::OnChange
IRelationshipClass::DeleteRelationship
IRelationshipClassEvents::OnDelete
![]() |
The IRelationshipClass::DeleteRelationshipsForObject() and IRelationshipClass::DeleteRelationshipsForObjectSet() generate one relationship class event for every relationship involved, of course. |
ArcFM listens to Relationship Class Events through a geodatabase class extension that resides on ArcFM Objects. This class extension calls the Autoupdater framework, which fires the assigned relationship autoupdater strategies.
Remember that attributed relationships are a special kind of Esri Relationship that stores additional fields. These Attributed Relationship objects implement IRow, and editing the additional fields causes IRow::Store to get called.
4.1 When Do Relationship Class Events Get Fired?
Obviously, they get fired when the relationship is edited. Note that CreateRelationship is called after the two objects to be related are created, and DeleteRelationship is called before the related objects are deleted. Of course, you can relate and unrelate objects without creating or deleting the objects that make up the relationship.
This order must be kept in mind when writing autoupdaters. In a Create autoupdater, there is no sense in looking for related objects, because the relationships have not been built yet. Likewise, the relationships have already been destroyed by the time Delete autoupdater gets called.
5.1 Esri Relationship Split Policies
When a network edge is split, a decision has to be made what to do with the related objects. This is defined by a relationship split policy, as described in the table below:
Relationship Split Policy
Description
esriRSPUseDefault
The default behavior, which is EsriRSPPreserveOnLargest for simple relationships and esriRSPDeleteParts for composite relationships
esriRSPPreserveOnLargest
Preserve related objects and create a relationship with the Feature with the largest part of the split geometry.
esriRSPPreserveOnSmallest
Preserve related objects and create a relationship with the Feature with the smallest part of the split geometry.
esriRSPPreserveOnAll
Preserve related objects and create a relationship with both Features. This option is not valid with relationships with 1..1 cardinality or composite relationships.
esriRSPDeleteRelationship
Delete the relationship.
esriRSPDeleteParts
Delete the related objects.
5.2 BeforeSplit and AfterSplit Autoupdaters
5.2.1 The ConductorInfo Problem
In the ArcFM Electric data model, conductors are modeled as network edges, while characteristics of the individual wires are modeled as related objects (ConductorInfo). When a conductor is split, the desired behavior is that the related ConductorInfo objects are duplicated. In other words, for each ConductorInfo record related to the original edge, there should be a ConductorInfo record (with identical attributes) related to each of the resulting edges after the split.
A quick perusal of the Relationship Split Policy table above will reveal that there is no mechanism built-in to ArcObjects to achieve this behavior.
5.2.2 Solving the ConductorInfo Problem
Schneider Electric solved this problem in a very complex way. What we did was overload the Split() method in our ArcFM objects. The overloaded behavior is to generate a pseudo-event for BeforeSplit and AfterSplit. The program logic is as follows:
5.2.3 Using BeforeSplit and AfterSplit for Other Purposes
As you can probably imagine from reading the above section, the logic for the BeforeSplit/AfterSplit is a very complex, highly-orchestrated set of code. In addition to the complexity described above, Designer adds additional logic to replicate GUs and CUs in the design tree.
The Esri Geodatabase team was heavily consulted while building the above code. They agree with us that this is not the best way to solve this problem. We have had several conversations with them in an attempt to convince them to create a new split policy that will copy related objects automatically. If this happens, we will probably drop support for the BeforeSplit and AfterSplit events.
For this reason, we recommend that any developer who wishes to make use of these events for their own purposes contact the Schneider Electric product team before doing so.
6.1 Problems with MM_E_CANCELEDIT
Returning MM_E_CANCELEDIT from an autoupdater object is a useful tool to prevent a feature from being edited. It’s important to understand how this works.
At the end of the chain, the code that called the Esri edit method receives an MM_E_CANCELEDIT error code. The ArcFM Solution editing tools know that this is a "special" error, and silently fail.
Regrettably, the ArcMap editing tools (e.g., the Move tool), with no knowledge of our framework, usually respond with an error message to the user. End-users are often confused by this message, but there is nothing that Schneider Electric can do about this. We have repeatedly tried to convince Esri to provide us with a special error code that is silently ignored by the ArcMap editing tools, but they have not yet agreed to implement this functionality.
6.2 Edit Operations
Edit Operations are used by ArcObjects to define a set of edits that can be undone/redone as a group. They are also used to define editing states in a versioned geodatabase. Edit Operations are created with a call to StartOperation. They can be successfully committed with a call to StopOperation or rolled by a call to AbortOperation. It is extremely important to realize that calls to these routines cannot be nested. In other words, each and every call to StartOperation must be paired with one and only one call to either StopOperation or AbortOperation. In addition, it is not possible to tell whether or not an operation has already been started.
Typically, these restrictions are not a problem. An editing tool, such as the ArcFM Attribute Editor or the ArcMap Delete tool will use the following program flow:
The only real problem comes about if an autoupdater tries to call AbortOperation itself, usually in a misguided attempt to abort the edit. As you can see above, however, this will result in mismatched edit operation calls. The Esri Geodatabase team has warned us that this can corrupt the operation stack. This is turn can corrupt the geometric network, or the version state tree. Worse yet, the code can appear to work, but can be silently corrupting data in the background. Under no circumstances should you call StartOperation, StopOperation, or AbortOperation in an autoupdater.