5

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?

Darcy
  • 5,228
  • 12
  • 53
  • 79

3 Answers3

8

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.

kemiller2002
  • 113,795
  • 27
  • 197
  • 251
  • This would mean I have to do that in every ActionResult correct? You can't do that at the repository level as far as I know, because the context is at the class level. It would be nice not to have to edit 1000 methods – Darcy Nov 15 '10 at 22:38
  • Then you want the repository to implement IDisposable, so that it can be disposed of when it is done. You should implement a finalizer etc. to handle your open connections etc. Check out the link I have on Dispose and Finalize and it will show you how to implement it. – kemiller2002 Nov 15 '10 at 22:40
2

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

Community
  • 1
  • 1
Darcy
  • 5,228
  • 12
  • 53
  • 79
  • Do you ever call the controller's overridden Dispose method explicitly in your code? Or is it taken care of implicitly? – stackPusher Sep 26 '15 at 17:10
1

DataContext (your repository) must implement IDisposable.

Ideally you need a UnitOfWork to pass to repositories and that implements IDisposable. Here you are leaving it down to the client to call another method which is not good.

Aliostad
  • 80,612
  • 21
  • 160
  • 208