开发者

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?


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.


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


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜