Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Am I using DataContext.Dispose() properly?

I've been getting lots of connection pool timeouts in my ASP.NET MVC project. I've been reading that even though Linq-to-SQL should be disposing for me it doesn't always work and also that not manually disposing anything that inherits IDisposable is bad practice.

I'm using the repository pattern that all my Linq-to-SQL statements use. Not knowing where to put the DataContext.Dispose() method, I put it in the SubmitChanges() function that consists of two lines of code:

public void SubmitChanges()
{
    db.SubmitChanges();
    db.Dispose();
}

Is this a good place to do this or am I doing it completely wrong?

like image 631
Darcy Avatar asked Nov 15 '10 22:11

Darcy


2 Answers

If it implements IDisposable the easiest way to do it is:

using(var context = new DataContext()){
  blah blah
}

This ensures it is disposed at the appropriate time.

  1. Open it.
  2. Do what you need to do.
  3. Close it.

This way you don't have to worry about it hanging around, and not getting called because of an exception etc.

The dispose key word (MSDN Link).

Since they are related, here is a link about Dispose and Finalize. It sounds like in this case, you want to implement the Repository so that it implements IDisposable. This way the calling object can create it, do what it needs to do and close it. You then can clean up the data context when it is disposed/finalized.

like image 137
kemiller2002 Avatar answered Sep 22 '22 04:09

kemiller2002


Well after some more digging I came across this post:

http://stephenwalther.com/blog/archive/2008/08/20/asp-net-mvc-tip-34-dispose-of-your-datacontext-or-don-t.aspx

and in the comments section Craig Stuntz wrote:

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.

So you should always Dispose any object which implements IDisposable.

In the case of Controllers and DataContexts, this turns out to be really easy, because Controller also implements IDisposable, and hence has a virtual Dispose method you can override. So you don't have to wrap your use of DataContext in a using. You can create it in the constructor (or wherever) and then dispose in the overridden Controller.Dispose. In this case, using IQueryable in the view works just fine, because the framework does not Dispose the Controller until the View has been rendered.

So I did what Craig suggested and overrode the Dispose method that the Controller inherits.

At the top of my controller code:

    Repository repository;

    // Default Contructor
    public MyController()
    {
        repository = new Repository();
    }

    protected override void Dispose(bool disposing)
    {
        repository.Dispose();
    }

and in my Repository I have a method called Dispose that looks like:

    public void Dispose()
    {
        db.Dispose();
    }

where db is my DataContext.

Now my overriden Dispose method gets called every time :) and I don't have to wrap all my ActionResult in using blocks

like image 26
Darcy Avatar answered Sep 21 '22 04:09

Darcy