What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

I’ve written a few posts about LINQ to SQL and am generally a big fan of the technology (even with its weaknesses) since it’s very productive.  After creating a custom DataContext object using the LINQ to SQL designer (or one created by hand) I always ensure that the object is wrapped in a “using” statement so that the Dispose() method is called:

using (MyDataContext context = new MyDataContext())
{

//Perform query }

I had assumed that not properly disposing of the DataContext object would lead to orphan SQL connections which is of course bad and will likely lead to your DBA holding a grudge against you for life. :-)

Steven Walther recently posted on the subject of disposing of DataContext objects and provided some interesting insight into what actually happens.  From what he says it sounds like the DataContext object acts much like the SqlDataAdapter class.  It opens the connection right before a query is executed and closes it immediately after.  I don’t want to steal Steven’s thunder so check out his post on the subject (the last part of the article talks about the consequences…or lack of consequences…of not calling Dispose()). 

I haven’t had time to verify the details in Reflector yet, but given that Steven’s one of the more intelligent people I know I’m confident that the details he presents are accurate.  It still feels more correct to wrap “using” statements around any object that implements IDisposable or explicitly call Dispose() in my opinion, but it’s good to know how the DataContext object works behind the scenes.

Published Tuesday, August 19, 2008 10:51 PM by dwahlin
Filed under: , ,

Comments

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Wednesday, August 20, 2008 8:52 AM by Steve

I don't think he is right this time.  See the comment by Paul Wilson.

I will have to agree here with Paul.

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Wednesday, August 20, 2008 12:35 PM by dwahlin

Steve,

Paul only says that he believes any IDisposable object should be disposed of properly and that as developers we shouldn't worry about the internal workings of objects like DataContext.  Having said that, I fully agree with what he says and will continue to wrap "using" statements around the context object.  What Steven points out is interesting to know though but definitely subject to change in future releases.

Craig Stuntz added the following comment to Steven's blog about what happens if an object isn't disposed though which is also interesting.  The only thing is...he uses the word "typically" which makes me wonder if this always happens or only in some situations:

"Failing to Dispose an object which implements IDisposable typically results in the object going into the finalization queue (read Chapter 19 of Jeffrey Richter's Applied Microsoft .NET Framework Programming for details). The results of this is that an object's memory that might have otherwise been freed in generation 01 be freed until a later generation collection.  If you're creating a lot of these objects, well, do the math."

 Either way...I'm still a fan of explicitly disposing of any object that implements IDisposable so it's a moot point for me.

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Wednesday, August 20, 2008 3:34 PM by Craig Stuntz

dwhalin,

"typically" means that if (1) the type has a Finalize/"destructor" (usually true if implementing IDisposable; it's part of the pattern) and (2) GC.SuppressFinalize(this) hasn't been called (generally true if you haven't called Dispose) then the instance goes into the finalization queue after it becomes unreferenced.

In other words, it's an implementation detail. You should presume this is the case unless you know otherwise, and even then it could change later.

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Wednesday, August 20, 2008 5:41 PM by PaulWilson

Here's the "typically" details:

The .NET Garbage Collector never ever worries about IDisposable.  What it does worry about is finalizers.  If an object has a finalizer that hasn't been suppressed then it won't be released in the first GC pass.  And "typically" objects that implement IDisposable have finalizers, since you probably would want to make sure that your "Dispose" logic is called even if the Dispose method itself is not called.  But I've seen some IDisposable objects that do not have finalizers, and I think I've even seen some in the framework itself when there wasn't anything really useful in the Dispose method anyhow.  But again, you shouldn't make unnecessary assumptions -- if it implements IDisposable then you should call Dispose (via a using block in most cases), and you should assume it could cost you extra GC cycles if you don't.

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Thursday, August 21, 2008 3:24 AM by dwahlin

Paul and Craig,

Thanks for the additional details.  Good stuff with the finalizers (something I haven't had to think much about for awhile).  It reenforces the fact that we all need to keep wrapping IDisposable objects in "using" blocks which has always been considered "best practice" anyway.

# re: What If I Don’t Call Dispose() on my LINQ to SQL DataContext Object?

Thursday, September 18, 2008 4:39 AM by Mike

Disposable != only used in using block. It should be disposed by the object that created it. In a repository pattern, your repositories should share a context (for object tracking to work). So they can't use the context in a using block. Instead, the context should be made available to them, and should only be disposed if some unit of work is done.

So if you have to update 1 record A and 2 related records B, only after that is all done, by the same context, can you dispose of it. You could have a context per http request, and an http module to create it and dispose of it at the end of the request cycle.

Does that make sense, because that's just my understanding, not 'validated' or any thing.

Thanks!