Object States and Change-Tracking
LINQ to SQL objects always participate in some state. For example, when LINQ to SQL creates a new object, the object is in
Unchanged state. A new object that you yourself create is unknown to the DataContext and is in
Untracked state. Following successful execution of SubmitChanges, all objects known to LINQ to SQL are in
Unchanged state. (The single exception is represented by those that have been successfully deleted from the database, which are in
Deleted state and unusable in that DataContext instance.)
The following table lists the possible states for LINQ to SQL objects.
||An object not tracked by LINQ to SQL. Examples include the following:
- An object not queried through the current DataContext (such as a newly created object).
- An object created through deserialization
- An object queried through a different DataContext.
||An object retrieved by using the current DataContext and not known to have been modified since it was created.|
||An object which is attached to a DataContext. For more information, see Data Retrieval and CUD Operations in N-Tier Applications (LINQ to SQL).|
||An object not retrieved by using the current DataContext. This causes a database
||An object known to have been modified since it was retrieved. This causes a database
||An object marked for deletion, causing a database
||An object that has been deleted in the database. This state is final and does not allow for additional transitions.|
You can explicitly request
Inserts by using InsertOnSubmit. Alternatively, LINQ to SQL can infer
Inserts by finding objects connected to one of the known objects that must be updated. For example, if you add an
Untracked object to an EntitySet<TEntity> or set an EntityRef<TEntity> to an
Untracked object, you make the
Untracked object reachable by way of tracked objects in the graph. While processing SubmitChanges, LINQ to SQL traverses the tracked objects and discovers any reachable persistent objects that are not tracked. Such objects are candidates for insertion into the database.
For classes in an inheritance hierarchy, InsertOnSubmit(
o) also sets the value of the member designated as the discriminator to match the type of the object
o. In the case of a type matching the default discriminator value, this action causes the discriminator value to be overwritten with the default value. For more information, see Inheritance Support.
An object added to a
Table is not in the identity cache. The identity cache reflects only what is retrieved from the database. After a call to InsertOnSubmit, the added entity does not appear in queries against the database until SubmitChanges is successfully completed.
You mark a tracked object
o for deletion by calling DeleteOnSubmit(o) on the appropriate Table<TEntity>. LINQ to SQL considers the removal of an object from an EntitySet<TEntity> as an update operation, and the corresponding foreign key value is set to null. The target of the operation (
o) is not deleted from its table. For example,
cust.Orders.DeleteOnSubmit(ord) indicates an update where the relationship between
ord is severed by setting the foreign key
ord.CustomerID to null. It does not cause the deletion of the row corresponding to
LINQ to SQL performs the following processing when an object is deleted (DeleteOnSubmit) from its table:
When SubmitChanges is called, a
DELETEoperation is performed for that object.
The removal is not propagated to related objects regardless of whether they are loaded. Specifically, related objects are not loaded for updating the relationship property.
After successful execution of SubmitChanges, the objects are set to the
Deletedstate. As a result, you cannot use the object or its
idin that DataContext. The internal cache maintained by a DataContext instance does not eliminate objects that are retrieved or added as new, even after the objects have been deleted in the database.
You can call DeleteOnSubmit only on an object tracked by the DataContext. For an
Untracked object, you must call Attach before you call DeleteOnSubmit. Calling DeleteOnSubmit on an
Untracked object throws an exception.
Removing an object from a table tells LINQ to SQL to generate a corresponding SQL
DELETE command at the time of SubmitChanges. This action does not remove the object from the cache or propagate the deletion to related objects.
To reclaim the
id of a deleted object, use a new DataContext instance. For cleanup of related objects, you can use the cascade delete feature of the database, or else manually delete the related objects.
The related objects do not have to be deleted in any special order (unlike in the database).
You can detect
Updates by observing notifications of changes. Notifications are provided through the PropertyChanging event in property setters. When LINQ to SQL is notified of the first change to an object, it creates a copy of the object and considers the object a candidate for generating an
For objects that do not implement INotifyPropertyChanging, LINQ to SQL maintains a copy of the values that objects had when they were first materialized. When you call SubmitChanges, LINQ to SQL compares the current and original values to decide whether the object has been changed.
For updates to relationships, the reference from the child to the parent (that is, the reference corresponding to the foreign key) is considered the authority. The reference in the reverse direction (that is, from parent to child) is optional. Relationship classes (EntitySet<TEntity> and EntityRef<TEntity>) guarantee that the bidirectional references are consistent for one-to-many and one-to-one relationships. If the object model does not use EntitySet<TEntity> or EntityRef<TEntity>, and if the reverse reference is present, it is your responsibility to keep it consistent with the forward reference when the relationship is updated.
If you update both the required reference and the corresponding foreign key, you must make sure that they agree. An InvalidOperationException exception is thrown if the two are not synchronized at the time that you call SubmitChanges. Although foreign key value changes are sufficient for affecting an update of the underlying row, you should change the reference to maintain connectivity of the object graph and bidirectional consistency of relationships.