我的ASP.NET MVC项目中已经获得了大量的连接池超时。我一直在阅读,即使Linq-to-SQL应该为我处理它并不总是有效,而且不是手动处理继承IDisposable
的任何东西都是不好的做法。
我使用的是所有Linq-to-SQL语句都使用的存储库模式。不知道将DataContext.Dispose()
方法放在何处,我把它放在由{2}代码组成的SubmitChanges()
函数中:
public void SubmitChanges()
{
db.SubmitChanges();
db.Dispose();
}
这是一个做这个的好地方还是我完全错了?
答案 0 :(得分:7)
如果它实现了IDisposable,最简单的方法是:
using(var context = new DataContext()){
blah blah
}
这可确保在适当的时间进行处理。
通过这种方式,您不必担心它会被挂起,也不会因为异常等而被调用。
The dispose key word (MSDN Link)
由于它们是相关的,因此这里有一个关于Dispose and Finalize的链接。听起来在这种情况下,您希望实现存储库,以便它实现IDisposable。通过这种方式,调用对象可以创建它,执行它需要做的事情并关闭它。然后,您可以在处理/完成数据上下文时清理它。
答案 1 :(得分:2)
经过一番挖掘后,我发现了这篇文章:
并在评论部分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
。在这里,您将其留给客户调用另一种不好的方法。