我将linq封装到存储库类中的sql调用,该类在我的重载控制器的构造函数中实例化。我的存储库类的构造函数创建数据上下文,以便在页面加载的生命周期中,只使用一个数据上下文。
在我的存储库类的析构函数中,我明确地调用了DataContext的dispose,尽管我不相信这是必要的。
使用性能监视器,如果我观察用户连接数并反复加载页面,则每页加载时数量会增加一次。连接不会被关闭或重复使用(大约20分钟)。
我尝试在我的配置中放置Pooling = false,看看是否有任何效果,但事实并非如此。在使用池的任何情况下,我都不希望每个负载都有新的连接,我希望它可以重用连接。
我已经尝试在析构函数中设置一个断点,以确保处置被击中并确定它已经被击中。那么发生了什么?
一些代码用于说明我上面所说的内容:
控制器:
public class MyController : Controller
{
protected MyRepository rep;
public MyController ()
{
rep = new MyRepository();
}
}
存储库:
public class MyRepository
{
protected MyDataContext dc;
public MyRepository()
{
dc = getDC();
}
~MyRepository()
{
if (dc != null)
{
//if (dc.Connection.State != System.Data.ConnectionState.Closed)
//{
// dc.Connection.Close();
//}
dc.Dispose();
}
}
// etc
}
注意:我向DC添加了一些提示和上下文信息,以便进行审计。这就是为什么我希望每页加载一个连接
更新 在我的存储库和我的控制器类上实现了IDisposable后,我无法找到一种方法来专门调用我的控制器上的Dispose方法,因为MvcHandler在后台创建和销毁控制器。但是我确实发现我的连接正在被关闭。我不知道这是否有效,但我不知道为什么这样做,我做了一些挖掘,发现MSDN引用让我开心:
执行完成后,MvcHandler将检查控制器是否实现了IDisposable接口,如果是,则调用控制器上的Dispose来清理非托管资源。
最终更新 经过一个月左右的工作,我现在已经删除了所有这些代码,并在我的公共存储库方法中围绕代码包装“using”语句并将此DC传递给私有方法。这似乎有点浪费和重复,并导致更多的连接被打开和关闭。但我得到了linq到sql缓存,我只能通过重置DC来解决。
答案 0 :(得分:4)
这里正确的模式(简短但足够的版本)是:
public class MyRepository : IDisposable
{
... // everything except the dtor
public void Dispose()
{
if (dc != null)
{
dc.Dispose();
}
}
}
public class MyController : Controller, IDisposable
{
protected MyRepository rep;
public MyController ()
{
rep = new MyRepository();
}
public void Dispose()
{
if (rep!= null)
{
rep.Dispose();
}
}
}
现在你可以(应该)使用带有using子句的MyController:
using (var ctl = new MyController ())
{
// use ctl
}
修改强>
刚注意到它级联到MyController,添加了代码。这显示了非托管资源的间接所有权如何扩散。
编辑2:
这也是正确的(因为这将是一次尝试/最终):
var ctl = GetController ();
using (ctl)
{
// use ctl
}
如果你不能将它保持为1方法的本地,那么就尽可能在Closing事件中调用ctl.Dispose()等。
答案 1 :(得分:2)
只有GC调用析构函数。你的MyRepository应该实现Dispose模式,并在那里处理dc。
有关详细信息,请参阅此问题。 In C# what is the difference between a destructor and a Finalize method in a class?
MyRepository应该实现IDisposable,如果你在对象的整个生命周期中打开它们,那么任何一次性对象都应该被丢弃。
大多数情况下,当您使用Disposable对象时,应将其包装在using块中
即
using(var dc = getDC())
{
//do stuff with the dc
}//the dc will be Disposed here
编辑:链接到c#析构函数的语言指南 http://msdn.microsoft.com/en-us/library/66x5fx1b(v=VS.100).aspx
答案 2 :(得分:0)
我同意一次性作品不正确的事实,Henk Holterman和Darryl Braaten的上述建议非常好,我认为它不能回答你的基本问题。
您的问题的答案是在MyRepository上调用Dispose(假设它是一个DataContext)不会关闭连接。它只返回到池的连接以供下次使用。
This SO Post,解释何时应该担心关闭连接......