The ability to obtain change notifications is important for building applications having the need to maintain logs of previous changes. The goal is to support such application scenarios while minimizing the resulting performance impact.
The ITracking interface provides events that can be used to track changes on objects. Such events can be used to implement custom change tracking models. An instance of this interface can be obtained via the new IObjectContext (implemented by both the ObjectContainer and the ObjectScope) property Tracking. This interface lists all common database object operations for the IObjectScope and the ObjectContainer.
Currently, there are four actions that raise tracking events: adding an object to an IObjectContext – Add(), removing an object from it's context – Remove(), refreshing the content of an object from the database – Refresh(), or when a modifying access to an object is performed. The events are only raised when a matching handler is present. All four events come in a "before" and an "after" flavor: Adding/Added, Changing/Changed, Removing/Removed and Refreshing/Refreshed.
When the Adding event is raised, the object is not known yet to the object context, and therefore the object identity is only available after the Add method has been executed.
In order to provide a time and memory efficient tracking API, the event arg instances passed to the event handler delegates are reused. That means that, the same instance is used when the Changing event is raised and when the Changed event is raised. To distinguish between the two usages, a property Finished has been implemented on the PersistenceEventArgs class, which changes its value to true for the "after" event.
When int/float/string.. fields are changed the respective changing/changed handler will get a copy of the old and new values. However, when a collection or a map is changed, the respective changing/changed events are raised, but the values obtainable by the ChangeEventArgs.OldValue and ChangeEventArgs.NewValue are not copies of the modified collection/map, and therefore changing them again in the event handler is not supported.
In order to avoid modifying actions programmatically, an exception can be thrown by the event handler.
For examples on how to use the change tracking refer to OpenAccess Tasks