BG1*_*100 7 c# datacontext dispose idisposable linq-to-sql
我有一个非常重的数据库访问的Web服务.它在测试中运行良好,但是一旦我将它投入生产并加速加载,它就会开始产生在DataContext中调用某个方法时引发的错误.错误通常是以下之一:
你调用的对象是空的
无法访问已处置的对象.对象名:'Dispose后访问的DataContext.'.
但不总是.
任何单个Web服务请求都可能导致多达10或15个数据库查询以及1或2个更新.
我设计了一个带有数据访问层的应用程序,这是一组对象,表示我的数据库中包含所有业务逻辑的表.这是我的Web服务的一个单独项目,因为它与Web GUI共享.
数据访问对象派生自基类,该基类具有在GetDataContext()需要时启动数据上下文实例的方法.
在我编写的所有数据访问对象中:
using (db = GetDataContext())
{
// do some stuff
}
Run Code Online (Sandbox Code Playgroud)
它为每个数据库交互愉快地创建/使用/处置我的DataContext(由sqlmetal.exe创建)对象.
经过几个小时的搔痒,我想我已经确定我的错误的原因是在加载时datacontext对象正在被创建和处理太多,我需要更改东西以共享相同的datacontext持续时间Web服务请求.
我发现这篇文章在互联网上有一个DataContextFactory,似乎完全符合我的需要.
但是,现在我已经实现了这个,并且DataContext被保存为HttpContext中的一个项目,我得到...
无法访问已处置的对象.
对象名:'Dispose后访问的DataContext.'
...每当我的datacontext被多次使用时.这是因为我的using (...) {}代码在首次使用后处理我的datacontext.
所以,我的问题是......在我浏览整个数据访问层并删除负载之前usings,有什么方法可以做到这一点?我不想通过取出内存泄漏usings,但同时我想在不同的数据访问对象之间共享我的datacontext.
我应该usings在我从Web服务请求返回之前删除,并手动调用dispose方法吗?如果是这样,我怎么去确保我抓住所有的东西,记住我有几个try-catch块可能会弄乱.
还有另一种更好的方法吗?我应该忘记处理并希望一切都被隐瞒了吗?
UPDATE
问题似乎不是性能问题......请求处理非常快,不超过200毫秒.事实上,我已经通过生成大量虚假请求进行负载测试而没有任何问题.
据我所知,它与负载有关的原因有两个:
当问题确实发生时,应用程序池将进入错误状态,并需要循环才能使其再次运行.
我自己设法解决了这个问题...
我有一个基类,它有一个创建 DataContext 实例的方法,如下所示:
public abstract class MyBase {
protected static DataContext db = null;
protected static DataContext GetDataContext() {
return new DataContext("My Connection String");
}
// rest of class
}
Run Code Online (Sandbox Code Playgroud)
然后,在我想要执行查询的继承 MyBase 的类中,我有这样的语句:
using (db = GetDataContext()) { ... }
Run Code Online (Sandbox Code Playgroud)
问题是,我想从静态方法和非静态方法访问数据库,因此在我的基类中,我将变量声明db为静态......大错误!
如果 DataContext 变量声明为静态,则在负载较重时,当同时发生很多事情时,DataContext 将在请求之间共享,并且如果 DataContext 上同时发生某些情况,则会搞砸 DataContext 的实例,并将数据库连接存储在应用程序池中以供所有后续请求,直到被回收,并且数据库连接被刷新。
因此,简单的修复方法就是更改此设置:
protected static DataContext db = null;
Run Code Online (Sandbox Code Playgroud)
对此:
protected DataContext db = null;
Run Code Online (Sandbox Code Playgroud)
using...这将破坏静态方法中的所有语句。但这可以通过在中声明 DataContext 变量来轻松解决using,如下所示:
using (DataContext db = GetDataContext()) { ... }
Run Code Online (Sandbox Code Playgroud)