Identity Resolution, State Management, and Change Tracking
The ObjectContext represents a container for in-memory objects. The object context, with the help of other classes and interfaces, manages an object's identity, state, original and current values of the object's properties, and tracks the changes made to each object in the cache. For information on how to attach objects to the object context, see Attaching and Detaching Objects. This topic discusses how the object context manages the change tracking, identity resolution, and state management.
Change Tracking
Change tracking information for the object graph is stored in ObjectStateEntry objects, which are created by the ObjectContext for each attached object. ObjectStateEntry objects store the following information for the entities:
The EntityKey that determines the identity of an entity.
The EntityState for the object
Information about related objects
The entity set name
The CurrentValues and OriginalValues of the entity's properties (objects in an Added state do not have original values)
The names of the entity's modified properties.
To find if the value of a property has changed between the calls to SaveChanges, query the collection of changed property names returned by the GetModifiedProperties method.
Note
If you are working with POCO entities without change-tracking proxies, you must call DetectChanges before calling GetModifiedProperties.
When an entity is detached, the corresponding ObjectStateEntry object is removed from the object context.
The ObjectStateEntry objects are managed by the ObjectStateManager. There is one instance of ObjectStateManager per object context. To get the ObjectStateEntry object for the specified entity, use one of the following methods on ObjectStateManager: TryGetObjectStateEntry, GetObjectStateEntry, or GetObjectStateEntries.
The object context is notified about changes made to properties of Entity Framework-generated entities and POCO change-tracking proxy objects as they occur and updates the state of objects and the values of properties in the ObjectStateEntry. The change reporting model involves reporting a pending change to a property, setting the property, and then reporting that the change is complete using the IEntityChangeTracker interface. The ObjectStateEntry manages POCO entities without change-tracking proxy objects and complex type objects differently. For more information, see Tracking Changes in POCO Entities.
The object context uses the information in the ObjectStateEntry objects to persist data to the data source. For more information, see Saving Changes and Managing Concurrency and How to: Execute Business Logic When Saving Changes.
Identity Resolution and Merge Options
The Entity Framework only maintains a single instance of an object with a specific entity key in the cache. The EntityKey objects are immutable objects that represent object's identity. Entity keys are used to perform identity resolution in the object context. For more information, see Working with Entity Keys. If an entity with the same identity is already being tracked, the data coming from the data source and the data already in the state manager are merged according to the MergeOption of the query.
The following table shows the possible merge options:
Member | Description |
---|---|
Objects that do not exist in the object context are attached to the context. If an object is already in the context, the current and original values of object's properties in the entry are not overwritten with data source values. The state of the object's entry and state of properties of the object in the entry do not change. AppendOnly is the default merge option. |
|
Objects that do not exist in the object context are attached to the context. If an object is already in the context, the current and original values of object's properties in the entry are overwritten with data source values. The state of the object's entry is set to Unchanged, no properties are marked as modified. |
|
Objects that do not exist in the object context are attached to the context. If the state of the entity is Unchanged, the current and original values in the entry are overwritten with data source values. The state of the entity remains Unchanged and no properties are marked as modified. If the state of the entity is Modified, the current values of modified properties are not overwritten with data source values. The original values of unmodified properties are overwritten with the values from the data source. In the .NET Framework version 4, the Entity Framework compares the current values of unmodified properties with the values that were returned from the data source. If the values are not the same, the property is marked as modified. In the .NET Framework version 3.5 SP1, the Entity Framework does not mark the property as modified, even if the value in the data source is different. Only modified properties are persisted to the data source when you call SaveChanges. To preserve the 3.5 SP1 behavior, set UseLegacyPreserveChangesBehavior to true. The PreserveChanges option can be used to resolve optimistic concurrency exceptions while preserving changes in the local context. For more information, see Saving Changes and Managing Concurrency. |
|
Objects are maintained in a Detached state and are not tracked in the ObjectStateManager. However, Entity Framework-generated entities and POCO entities with proxies maintain a reference to the object context to facilitate loading of related objects. |
Entity State
The object context must know the state of an object to save changes back to the data source. ObjectStateEntry objects store EntityState information. The SaveChanges methods of the ObjectContext process entities that are attached to the context and update the data source depending on the EntityState of each object. For more information, see Creating, Adding, Modifying, and Deleting Objects. The following table shows the possible states of an object:
Member | Description |
---|---|
Added |
The object is new, has been added to the object context, and the SaveChanges method has not been called. After the changes are saved, the object state changes to Unchanged. Objects in the Added state do not have original values in the ObjectStateEntry. |
The object has been deleted from the object context. After the changes are saved, the object state changes to Detached. |
|
Detached |
The object exists but is not being tracked. An entity is in this state immediately after it has been created and before it is added to the object context. An entity is also in this state after it has been removed from the context by calling the Detach method or if it is loaded by using a NoTracking MergeOption. There is no ObjectStateEntry instance associated with objects in the Detached state. |
Modified |
One of the scalar properties on the object was modified and the SaveChanges method has not been called. In POCO entities without change-tracking proxies, the state of the modified properties changes to Modified when the DetectChanges method is called. After the changes are saved, the object state changes to Unchanged. |
Unchanged |
The object has not been modified since it was attached to the context or since the last time that the SaveChanges method was called. |
The state of objects inside an object context is managed by the ObjectStateManager. To find out the state of an object, call one of the following ObjectStateManager methods: TryGetObjectStateEntry, GetObjectStateEntry, or GetObjectStateEntries. The State property of the ObjectStateEntry defines the state of the object.