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.
Comments
- Anonymous
October 13, 2005
This is great! It's good to hear that you're dealing with the full E2E flow for DB data. - Anonymous
October 13, 2005
The comment has been removed - Anonymous
October 15, 2005
Mike: Yes, who doesn't :-)
(I mean: use codesmith for generating all those adapters and datasets and stuff).
And yes, I can't wait to see DLinq being used for real apps. - Anonymous
October 15, 2005
Nice post Dinesh.
I had developed a Business Layer Strongly Typed on DLinq with Many-to-Many support.
Simple struct database: Users and Groups as like project sample.
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=109996
Cheers,
Javier Luna - Anonymous
October 17, 2005
Mike's comment is fair - code gen for DataAdapters does reduce complexity. But this is where the difference between builders of object model vs users of a business object model comes into picture. The DLinq story is that someone can set up the mapping once and everyone can do queries against the object model. Perhaps I will do more contrasting in a separate post.