3

我已经收到了一些代码,并且在控制器类中有一个保存初始化数据库上下文的属性。

public class MyController: Controller
{
    protected AssetManagerContext db = new AssetManagerContext("ConnectionString");
    // Actions...etc.

    [HttpGet]
    public ActionResult Edit(int id)
    {
        MyAsset myAsset = db.Assets.Find(id); // Used and not disposed
        return View(myAsset);
    }
 }

大多数操作都使用了这个 Context 而没有释放它,我担心的是这个上下文是打开的。

  1. 我是否需要担心这个上下文没有被显式关闭(通过 .Dispose() 或 using {} 语句

  2. 如果我担心,我应该如何处理这种情况,因为变量是类的一部分并且跨动作使用?

4

4 回答 4

6

Controller 类有一个 dispose 方法。因此,在您的控制器中覆盖该方法并处理该上下文。

protected override void Dispose(bool disposing)
{
   base.Dispose(disposing);
   db.Dispose();
}

上下文完成后将自动调用它。

于 2012-08-23T16:57:26.270 回答
4

在对控制器的调用之间保持上下文打开绝不是一个好主意。

这会导致数据库连接一直保持到 MyController 实例被 GC 处理为止。

如果您的控制器完成与实体框架的所有交互(您的视图不需要延迟加载域对象),最简单的模式是

public class MyController : Controller
{
    public ActionResult MyAction(...)
    {
        using (AssetManagerContext db = new AssetManagerContext("ConnectionString"))
        {
            // Do stuff
        }
    }
}

如果您的视图确实需要从上下文中延迟加载对象,您确实可以将上下文对象的引用作为类的属性并按照@Kundan 的建议实现 IDisposable。

于 2012-08-23T16:55:41.697 回答
2

实际上,这并不重要。正如 Stephen Walter在评论中发布指向他的一个博客条目的链接时指出的那样,清理数据上下文并不是特别重要,因为最终,数据上下文在管理自己的连接和池化连接方面做得非常出色。

如果您不清理它,您分配的额外内存可能比它需要的时间更长,但它不会使连接保持打开的时间超过必要的时间。

然而,最好的做法是自己清理。即使您知道它(当前)并不重要。

于 2012-08-23T17:23:37.243 回答
0

首先,您应该始终明确地释放昂贵的资源,例如数据库连接、流等。不要依赖框架为您执行此操作。即使它现在这样做,你也永远不知道微软将来是否会改变这一点,给你留下一个你可能找不到的巨大漏洞。

using您可以使用块在每个操作中创建和处置上下文。

但是为了节省一些代码并遵循DRYOnActionExecuting原则,您可以通过分别覆盖and来实例化和处理每个操作之前和之后的上下文OnActionExecutedContext

public class MyController: Controller
{
    protected AssetManagerContext db;

    [HttpGet]
    public ActionResult Edit(int id)
    {
        MyAsset myAsset = db.Assets.Find(id); // Used and not disposed
        return View(myAsset);
    }

    protected override void OnActionExecuting(ActionExecutingContext db) {
        base.OnActionExecuting(db);
        db = new AssetManagerContext("ConnectionString");
    }

    protected override void OnActionExecuted(ActionExecutedContext db) {
        base.OnActionExecuted(db);
        db.Dispose();
    }
}
于 2012-08-23T16:59:25.113 回答