EntityFramework上下文释放

4
我写了几个使用Entity Framework的应用程序。我过去常常使用using子句。通过这个子句,我确信数据库连接会被正确关闭。
但是,在某些情况下,我的数据库上下文对象是一个类的字段。它的实例化在声明中完成,没有使用using子句。
我刚刚发现,在这种情况下,Dispose()方法不会被调用。使用using子句时,Dispose()会自动调用。
所以我的问题是: 如果在数据库上下文上没有调用Dispose()会发生什么?析构函数将被调用,因此您认为数据库会被析构函数关闭吗?还是应该在容器对象的析构函数中手动调用Dispose(),像这样:
class MyClass
{
    public MyDbContext ctx = new MyDbContext();

    ....

    ~MyClass()
    {
         ctx.Dispose();
    }
}

谢谢

2个回答

5
绝对不应该调用Dispose方法。尤其是显式调用。

当您使用using语句时,在try-finally块中会隐式调用Dispose()方法。这很好,但您不需要显式调用它。

为什么?

如果在异常发生之前遗漏了单独的显式的Dispose语句,则无法保证显式Dispose的执行。

以下是Rowan Miller [MSFT]的话:

DbContext的默认行为是,在需要时自动打开底层连接,并在不再需要时关闭连接。例如,当您执行查询并使用“foreach”迭代查询结果时,调用IEnumerable.GetEnumerator()将使连接打开,并且当没有更多结果可用时,“foreach”将负责调用枚举器上的Dispose以关闭连接。类似地,调用DbContext.SaveChanges()将在向数据库发送更改之前打开连接,并在返回之前关闭连接。

鉴于此默认行为,在许多实际情况下,将上下文留下而不进行处理并仅依靠垃圾回收是无害的。

话虽如此,我们的示例代码倾向于始终使用“using”或以其他方式处理上下文:

  1. 默认自动打开/关闭行为相对容易被覆盖:您可以通过手动打开连接来控制何时打开和关闭连接。一旦在代码的某个部分中开始这样做,忘记释放上下文就会变得有害,因为您可能会泄漏未关闭的连接。

  2. DbContext遵循推荐模式实现IDisposable,其中包括公开一个虚受保护的Dispose方法,派生类型可以重写该方法,例如需要将其他非托管资源聚合到上下文的生命周期中。

您可以在此处阅读更多内容:我必须始终在我的DbContext对象上调用Dispose()吗?不用

使用Entity Framework正确管理DbContext


只是一句话:当我使用try...finally时,dispose不会自动调用吗?因此使用do比try finally更好。 - Bob5421
当然可以。但是它会在 try,finally 块内隐式发生。当你显式使用时,情况就不同了。这就是为什么不建议显式调用 dispose。没有保证。 - Sampath
好的,谢谢。你知道是否有一种方法可以使用EF建立持久化数据库连接吗?我是一个老派的PHP开发者,我们过去常常使用持久连接,可能在多个HTTP请求之间共享,以提高性能。在ASP.Net MVC C#中是否也有类似的方式? - Bob5421
在处理Web应用程序时,每个请求使用一个上下文实例是最佳方式。我在我的帖子中放了一个链接,请阅读以获取更多信息。 - Sampath
@Sampath 看起来你没有区分“不需要”和“必须不”或“非常糟糕”的区别。这篇文章中唯一的真相就是从链接帖子中复制的文本,即在大多数情况下没有必要调用 DbContext.Dispose。关于隐式与显式的所有其他内容都只是你个人的观点。调用任何可处理对象的 Dispose 方法显式地多次也没有问题。 - Ivan Stoev
我根据 OP 的上下文提供了那些信息。这意味着当我们考虑 DbContext 场景时,可能会错过 separateexplicitDispose 语句,尤其是在之前发生异常的情况下。这就是为什么它不好。没有关于这个的保证。@IvanStoev - Sampath

2
如果您可以在父类上使用 using,那么请让它实现 IDisposable 接口:
class MyClass : IDisposable
{
    public MyDbContext ctx = new MyDbContext();

    ....

    public void Dispose()
    {
        ctx.Dispose();
    }
}

这样,在 using 语句中调用父类将在退出时处理您的上下文。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接