tags:

views:

4274

answers:

7

I have a project with a number of different classes querying and modifying data in a common set of tables. I've set up a .dbml file which provides us with a DataContext class. My question is whether a single instance of the DataContext should be used by all objects, or whether multiple instances are safe to use. I'm also wondering about thread safety in the case of a single DataContext, and whether access to it's methods should be synchronized.

A: 

I've always heard that you should use a single instance of the DataContext. I usually create a singleton instance of my DC in my business logic class, and use it for all my linq queries.

I'm sure some of the linq gurus on here might be able to give you exact reasons as to why you should only have on instance of your data context class... I'm not quite certain.

Rafe
That's vague and superstitious. Can you be more specific as to why you took this approach?
Dan Esparza
I've always heard quite the opposite. DataContexts are intended to be as short-lived as possible, in order to minimize concurrency problems.
Konamiman
+2  A: 

The problem with using a single data-context object is that you can get in trouble if you've added some changes to it's queue, and want to do a roll-back on just some of those queued changes.

That's why I use a data-context object for each of my classes--my User class has it's own data-context, my Application class has it's own, and so forth.

This pattern eliminates most troubles of doing roll-backs in my projects.

roosteronacid
+5  A: 

The DataContext class is lightweight enough that you can instantiate it over and over. This makes thing simpler when accessing entity objects within a single method. If you need to access the same LINQ objects from different classes and methods while keeping them attached to the DataContext for tracking purposes, it's also okay to keep a single instance.

Mark Cidade
+19  A: 

Rick Strahl has a nice article about your options: http://www.west-wind.com/weblog/posts/246222.aspx.

See also: http://stackoverflow.com/questions/196253/linq-to-sql-where-does-your-datacontext-live.

You may want a slightly different strategy for each type of deployment - web, desktop, windows service...

Summarized, your options are:

  • Global DataContext - dangerous in multi-threaded environments (including web apps). Remember that instance members are not guaranteed to be thread-safe (from Bradley Grainger's answer above).
  • DataContext per thread - complicated. If your DataContext is tracking changes you must be sure to flush them at the appropriate time. Instantiating, storing, and retrieving the DataContext is a pain.
  • DataContext per atomic action - you lose the ability to track changes since one DataContext creates an object while another updates or deletes it. Attaching a data object to a new DataContext may not work like you expect.
  • DataContext per data object - seems inelegant because you have to fuss with the DataContext on instantiation(create and attach) and update/delete (pull it off the data object and use it).

I opted for a DataContext per data object. It may not be the fanciest solution but it works in all deployment environments.

Corbin March
+5  A: 

I use an new instance of DataContext for every transaction.

Reusing old instances can be troublesome, and will bloat the content of the DataContext, since any item that has been loaded at some time, will have to be tracked - your app will get slower and slower, bloating up memory.

If you need an item longer than for a transaction, you can detach it from the DataContext by cloning the item, and can reattach it later to a new and fresh DataContext using Attach().
I even can clone an item, send it over the network with WCF, get it back in some later call, attach it to a new DataContext and save the changes (of course I need a timestamp column for this).

Sam
A: 

Singleton datacontext are best when you are doing presentation only layer, i think that singleton datacontext with lists and other shared data could be very nice, but:

  1. You should turn off deffered loading
  2. Load child data on demand
  3. Looking on datacontext size and sometimes renew it

But for data editation i beleave the best way is to crete new datacontect for each business object you are editing and attach it to the related editation form

Datacontext saves all changed data stored within all datacontext, theres no way to save just one record and moving it to another one... just create new datacontext for each object you want to edit (including childs)

pepa
Singletons are evil. You used the word "presentation" which might imply web-app which means threading.. + singletons = very evil!
cottsak
A: 

There is a serious problem with shared DataContexts: Identity cache becomes problematic cross-transactions. For instance you add a row to a table, SubmitChanges, rollback transaction, add the same row again, SubmitChanges, bam: "row already exists" exception.

Thus the smaller DataContext scope is the better. We usually stick to one DataContext per function. Occasionally that gets passed to sub-functions. Otherwise it becomes more likely to leave DataContext state dirty.

ssg