MVC 4,EF 4.3在应用程序请求的生命周期内管理上下文

时间:2012-04-21 16:05:07

标签: asp.net-mvc asp.net-mvc-3 entity-framework entity-framework-4

情况:我想要做的是访问页面生命周期的数据上下文。这主要是为了(a)避免一系列using()并避免(b)在访问延迟加载属性时视图中超出范围异常。

编辑:我正在使用MVC 4和Entity Framework 4.3.1(最新版)

我通常做的是

using (MyDB b = new MyDB()) {
 ...do all my stuff
}

在我的控制器或数据层中。根据我的阅读,这很好用的是它干净,没有内存泄漏等。但缺点是,即使对于单个页面的生命周期,我最终一次又一次地这样做,并且我的对象在因为我已经处理了上下文。

我做了一些阅读并在2009年发现了类似的帖子,但答案中没有代码。当然其他一些人已经想出如何解决这个问题 - 我想我必须做点什么

Application_BeginRequest and EndRequest

但我只是不确定如何以及陷阱/最佳实践是什么。

感谢您的帮助(如果可能,请提供一些代码示例!)

4 个答案:

答案 0 :(得分:2)

我看到你有一个asp.net MVC的标签,所以我认为这就是你正在使用的。

您应该实施类似http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

的存储库方法

无论如何,你真正需要做的就是在你的每个控制器上做这样的事情

private MyDB b = null;
public MyController()
{
      b = new MyDB();
}

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

答案 1 :(得分:1)

你希望使用你的datacontext的方式绝对是禁止的(除非你正在处理几百行数据库,在这种情况下为什么要使用EF)。

但是如果你有一个真正的生产规模的数据库,将上下文固定到应用程序范围将导致以下结果:

  • 因为你提到使用lazyload(我完全可以使用这个功能) 所有数据库都会迟早在服务器端切换 被哄骗到内存(上下文级实体缓存)
  • 您的实体实例将在请求和线程之间共享(是的, for write operations true)
  • EntitySet / DbSet除了线程安全外都是
  • 你的写作操作将完全缓慢且无法预测 无法保存“只是你的改变”,你将保存一切 自上次save / submitChanges以来已更改,您可能会保存其他线程 半烘焙实体

EF上下文是IDisposable有一个很好的理由:它应该用于紧凑,简短的操作,是的:你应该一直使用(...)“东西”。

如果您正在构建一个将由多人使用的网站,内部网搜索等,以上所有内容都只是一个问题。

答案 2 :(得分:1)

首先不要在视图中使用延迟加载(实体框架进入数据库并将结果一次返回一行),因为来自视图的查询是不好的做法并导致< strong>选择N + 1 (选择N + 1是数据访问反模式,其中以次优方式访问数据库。)或类似的不良做法。

使用多个对象上下文意味着每个请求使用多个数据库连接,导致数据库的额外压力和整体性能降低,每个对象上下文也不会知道其他对象上下文跟踪的实体必须再次查询数据库的当前状态或必须发出不必要的更新

在编写视图时,您不应该考虑持久性或您查看的查询数量而烦恼。

要点:

  1. 在操作中执行所有查询。

  2. 使用Include方法强制加载集合,以指定要包含在对象模型中的对象模型的哪些部分     初步查询。

  3. 每个请求使用一个对象上下文。
  4. 此致

答案 3 :(得分:0)

您可以在退出using块之前返回,以便在视图中延迟加载时上下文将在范围内

using (MyDB b = new MyDB()) {
 ...do all my stuff

  return View(b.Data);
}