Read Only Data Context

Some issues are like picking scabs, or so they seem.  They taunt you.  Call out to you.  Pick me!  Pick me!  And, you do.   Now, you’ve made it worse.  It’s bleeding again and no closer to healing.

I’ve seen this with LINQ to SQL.  By default, the data context has support for tracking database changes enabled.  This means a couple of things.  One, when you load data, it’ll be cached.  If you query the same items again, within the same data context, the framework will see the items in its cache, and just return them again.   Two, by default, if you try to save an item and it has been updated in the underlying database with a conflicting change, you’ll get an exception.  Three, this option automatically enables lazy loading of any child entities of the entity you are querying.

This may fit your intentions perfectly well, as its doing what it is designed to do, which is provide some concurrency handling.  But, what if you have an object that is just for monitoring?  You don’t want to show cached data, you want the data to be refreshed.  OK, pick that scab, and you’ll see support for refreshing data [DataContext.RefreshMode].  That option works great for pulling updates back into the context, but guess what (still) happens when something is deleted?  You’ll get an exception.

Another scab.  Now what?  Well, there’s an option to turn off the change tracking [DataContext.ObjectTrackingEnabled = false].  This is wonderful.  Now, each query will return to the database to get the latest data.  Note that when this option is set, you cannot submit changes to the data context.  That will throw an exception.  So, you have a data context that is read only.

The read only data context works well until you start trying to retro fit that option into existing data contexts.  Why, because the automatic lazy loading of child entities no longer occurs when the data context is read only.  And, if you have code that is expecting those entities to be “magically” populated with all of their data [foreach (var order in customer.Orders)], well, you have broken code.

There has to be a way to get that data out of the database, doesn’t there?  Go ahead, pick it.  Joining the child entity doesn’t work.  And, I’ve read some tricky query hacks posted in the void that look really juicy, but break down when you actually give it go.  Alas, there is an option [DataContext.LoadOptions].   This property allows you to do a whole host of neat things with the query.  But, mostly, it allows you to say “when entity x is queried, please load entity y” [dataLoadOptions.LoadWith<Customer>(c => c.Orders)].  This works great (and is also useful on the non-read only data context when you are working in a disconnected environment and an attempt to lazy load after the original query returns, would fail).

There are some things to be aware of though.  The lazy load options must be set before any query is attempted.  And, they apply to every query made with that data context.  There may, or may not, be issues there depending on the scope of work/lifetime of the data context(s) in your architecture, but it could be another scab that is begging to be picked.

Page 18 of 18« First...1415161718
Rss Feed