我如何正确管理的DataContext的处置? [英] How do I correctly manage the disposing of a DataContext?

查看:165
本文介绍了我如何正确管理的DataContext的处置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Web服务,它是对数据库的访问相当沉重。它工作正常,在试验,但只要我把它在生产和坡道负载它开始搅动了错误的东西时调用了DataContext的一个方法时引发。该错误通常是其中之一:

I have a web service that is quite heavy on database access. It works fine in test, but as soon as I put it in production and ramp up the load it starts churning out errors that are raised when something calls a method in the DataContext. The error is normally one of these:

对象引用未设置为一个对象

Object reference not set to an instance of an object

无法访问已释放的对象。对象名称:'。DataContext的处置后访问

Cannot access a disposed object. Object name: 'DataContext accessed after Dispose.'.

但并非总是如此。

任何单个的Web服务请求可能导致多达10个或15个数据库查询,以及1或2的更新。

Any single web service requests can result as many as 10 or 15 database queries, and 1 or 2 updates.

我设计我的一个数据访问应用程序层,是一堆代表我的数据库,其中包含所有业务逻辑的表对象。本是一个独立的项目,因为它与Web GUI共享我的web服务。

I've designed my application with a data access layer which is a bunch of objects that represent the tables in my database which hold all the business logic. The is a separate project to my web service as it's shared with a Web GUI.

数据访问对象,从其中有一个基类派生 。GetDataContext()方法来启动,只要它所需的数据上下文的实例

The data access objects derive from a base class which has a GetDataContext() method to initiate an instance of the data context whenever it's needed.

所有在我的数据访问对象我写的:

All throughout my data access objects I've written this:

using (db = GetDataContext())
{
    // do some stuff
}

而快乐地创建/使用/释放每一个我的DataContext(由sqlmetal.exe创建)对象,每个数据库的交互。

which happily creates/uses/disposes my DataContext (created by sqlmetal.exe) object for each and every database interaction.

挠头的几个小时后,我想我已经决定,我的错误的原因是,在负载下正在创建和设置在DataContext对象。太多了,我需要改变的东西,分享了Web服务请求的时间相同的datacontext

After many hours of head scratching, I think I've decided that the cause of my errors is that under load the datacontext object is being created and disposed way too much, and I need to change things to share the same datacontext for the duration of the web service request.

我发现的其中有似乎做什么,我需要一个DataContextFactory在互联网上这篇文章

然而,现在我实现了这一点,在DataContext被保存为HttpContext的一个项目,我得到...

However, now that I've implemented this, and the DataContext is saved as an item in the HttpContext, I get...

无法访问已释放的对象。

Cannot access a disposed object.

对象名称:处置后访问的DataContext。

Object name: 'DataContext accessed after Dispose.'

.. 。每当我的datacontext使用一次以上。这是因为我的使用(...){} 代码是处理第一次使用后,我的DataContext的。

...whenever my datacontext is used more than once. This is because my using (...) {} code is disposing my datacontext after its first use.

所以,我的问题是...我通过我的整个数据访问层之前,并删除 usings 的负荷,什么是做到这一点的正确方法?我不希望拿出来导致内存泄漏的 usings ,但在同一时间,我想在不同的数据访问对象分享我的DataContext。

So, my question is... before I go through my entire data access layer and remove loads of usings, what is the correct way to do this? I don't want to cause a memory leak by taking out the usings, but at the same time I want to share my datacontext across different data access objects.

如果我只是删除 usings ,并手动调用Dispose方法之前我从Web服务请求返回?如果是这样的话怎么去,我要确保我捕捉一切铭记我有可能会导致混乱几个的try-catch 块。

Should I just remove the usings, and manually call the dispose method just before I return from the web service request? If so then how go I make sure I capture everything bearing in mind I have several try-catch blocks that could get messy.

有另一种更好的方式来做到这一点?如果我只是忘了处理,并希望一切都隐含清理?

Is there another better way to do this? Should I just forget about disposing and hope everything is implicitly cleaned up?

更新

该问题不会出现是一个性能问题...请求非常迅速的处理,不超过约200毫秒。其实我已经负载通过产生大量的,没有任何问题的假请求测试它

The problem doesn't appear to be a performance issue... requests are handled very quickly, no more than about 200ms. In fact I have load tested it by generating lots of fake requests with no problems.

据我所看到的,它是负荷的原因有两个相关的:

As far as I can see, it is load related for one of two reasons:


  • 高数量的请求会导致并发请求互相影响

  • 问题发生更频繁地简单因为有大量的请求。

当确实发生了问题,应用程序池进入一个糟糕的状态,需要一个循环得到它的再次合作。

When the problem does occur, the application pool goes into a bad state, and requires a recycle to get it working again.

推荐答案

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

I managed to fix this myself...

我有一个基类,必须将创建的DataContext实例的方法,如:

I had a base class that had a method that would create the DataContext instance, like this:

public abstract class MyBase {

    protected static DataContext db = null;

    protected static DataContext GetDataContext() {
        return new DataContext("My Connection String");
    }

    // rest of class
}

然后,在继承MyBase,我想做我的查询类,我有这样的语句:

And then, in the classes that inherited MyBase where I wanted to do my queries, I had statements like this:

using (db = GetDataContext()) { ... }

的事情是,我想访问从静态方法和非静态方法的数据库,所以在我的基类,我会宣布分贝变量作为静态...大的错误!

The thing is, I wanted to access the database from both static methods and non-static methods, and so in my base class, I'd declared the db variable as static... Big mistake!

如果DataContext的变量声明为静态的,重载期间,当很多事情在DataContext的是在请求之间共享同一时间发生,如果事情发生在DataContext的正好同时它搞砸了DataContext的实例,并存储在应用程序池要求的所有后续直到它的回收数据库连接,数据库连接将被刷新。

If the DataContext variable is declared as static, during heavy loads when lots of things are happening at the same time the DataContext is shared among the requests, and if something happens on the DataContext at exactly the same time it screws up the instance of the DataContext, and the Database connection stored in the Application pool for all subsequent requested until it's recycled, and the database connection is refreshed.

所以,简单的解决方法就是改变这样的:

So, the simple fix is to change this:

protected static DataContext db = null;



这样:

to this:

protected DataContext db = null;



...这将打破所有的使用中的静态方法声明。但是,这可以很容易地通过宣布在DataContext的变量被固定在使用来代替,就像这样:

...which will break all of the using statements in the static methods. But this can easily be fixed by declaring the DataContext variable in the using instead, like this:

using (DataContext db = GetDataContext()) { ... }

这篇关于我如何正确管理的DataContext的处置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆