DLinq: Demystifying OR Updates

Here is another FAQ I got about DLinq at PDC. How does DLinq handle changes to objects? How is it similar to or different from ADO.NET DataAdapter? 

Here is a quick overview of what goes on under the covers at a conceptual level:

Before objects are modified:

  • Original values are copied for
    • Detecting changes; and
    • Detecting optimistic concurrency conflicts

After SubmitChanges() is called:

  • Modified objects in the object graph are identified. This includes changes in relationships between persistent objects - whether singleton references or collections of references
    • New objects to be inserted
    • Retrieved objects to be deleted
    • Retrieved objects whose persistent members have changed
  • Changes are ordered based on foreign key constraints. DB-generated key values that propagate to foreign keys are taken into account. 
  • Insert, update and delete statements are constructed with modified current  values in the set clause and original values in the where clause for optimistic concurrency conflict detection
  • Database connection is opened and a transaction is started. The insert / update / delete statements are executed as a batch in the context of the transaction
  • If there are any errors, the transaction is rolled back. Appropriate exception is thrown (e.g. optimistic concurrency exception in case of conflicts)
  • If the transaction succeeds, the internal state of the DataContext is changed accordingly.
  • Database-generated columns like autoincrement / GUID keys and timestamps are propagated back to the objects

Of course, this is a simplified description of what needs to be taken care of in the implementation. A couple of notable things are:

  • If you use our generated code (or implement similar code), we can optimize change tracking for space and time. Essentially, it is a "copy-on-write" optimization so it avoids copying objects that are not changed and it also reduces the processing required when SubmitChanges is called. The list of objects that are changed is roughly the list of objects copied.
  • If you have created insert / update / delete methods on a class derived from DataContext (e.g. for using stored procedures), those methods are called instead of generating and executing insert / update / delete commands.

In case of DataAdapter (required for persisting changes made in DataSet back to the database), you will need to do the following:

  • Create one DataAdapter per table 
  • Create up to three commands per adapter with appropriate parameters for original values etc.
  • Execute the updates in the right order depending on foreign key constraints. You have to be mindful of the different order required for insert and deletes.
  • Flow the server-generated key values appropriately.

So DLinq does a lot of work for you and simplifies your life greatly. After all, DLinq is about raising the abstraction level and bringing it on par with what modern OO languages provide.