我正确使用DataContext.Dispose()吗?

时间:2010-11-15 22:30:55

标签: c# linq-to-sql repository-pattern

我的ASP.NET MVC项目中已经获得了大量的连接池超时。我一直在阅读,即使Linq-to-SQL应该为我处理它并不总是有效,而且不是手动处理继承IDisposable的任何东西都是不好的做法。

我使用的是所有Linq-to-SQL语句都使用的存储库模式。不知道将DataContext.Dispose()方法放在何处,我把它放在由{2}代码组成的SubmitChanges()函数中:

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

这是一个做这个的好地方还是我完全错了?

3 个答案:

答案 0 :(得分:7)

如果它实现了IDisposable,最简单的方法是:

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

这可确保在适当的时间进行处理。

  1. 打开它。
  2. 做你需要做的事。
  3. 关闭它。
  4. 通过这种方式,您不必担心它会被挂起,也不会因为异常等而被调用。

    The dispose key word (MSDN Link)

    由于它们是相关的,因此这里有一个关于Dispose and Finalize的链接。听起来在这种情况下,您希望实现存储库,以便它实现IDisposable。通过这种方式,调用对象可以创建它,执行它需要做的事情并关闭它。然后,您可以在处理/完成数据上下文时清理它。

答案 1 :(得分:2)

经过一番挖掘后,我发现了这篇文章:

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

并在评论部分Craig Stuntz写道:

  

无法处理实现IDisposable的对象通常会导致对象进入终结队列(有关详细信息,请阅读Jeffrey Richter应用Microsoft .NET Framework编程的第19章)。结果是,在第01代中可能已释放的对象的内存将被释放,直到下一代集合为止。如果您正在创建大量这些对象,那么,请进行数学计算。

     

所以你应该总是处理任何实现IDisposable的对象。

     

对于Controllers和DataContexts,事实证明这很简单,因为Controller也实现了IDisposable,因此有一个可以覆盖的虚拟Dispose方法。因此,您不必在使用中包装DataContext。您可以在构造函数(或任何地方)中创建它,然后在重写的Controller.Dispose中进行处理。在这种情况下,在视图中使用IQueryable可以正常工作,因为框架在呈现视图之前不会处理Controller。

所以我做了Craig建议并覆盖了Controller继承的Dispose方法。

在我的控制器代码顶部:

    Repository repository;

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

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

在我的存储库中,我有一个名为Dispose的方法,如下所示:

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

其中db是我的DataContext

现在每次调用我的重写Dispose方法:)并且我不必将所有ActionResult包装在使用块中

答案 2 :(得分:1)

DataContext(您的存储库)必须实现IDisposable

理想情况下,您需要UnitOfWork传递给存储库并实现IDisposable。在这里,您将其留给客户调用另一种不好的方法。