如何正确管理DataContext的处理?

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毫秒.事实上,我已经通过生成大量虚假请求进行负载测试而没有任何问题.

据我所知,它与负载有关的原因有两个:

  • 大量请求会导致并发请求相互影响
  • 问题更频繁地发生,因为有很多请求.

当问题确实发生时,应用程序池将进入错误状态,并需要循环才能使其再次运行.

BG1*_*100 3

我自己设法解决了这个问题...

我有一个基类,它有一个创建 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)