1

情况:我想做的是访问页面生命周期的数据上下文。这主要是为了 (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

4 回答 4

2

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

您应该实现一个存储库方法,如http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-在-an-asp-net-mvc-应用程序中

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

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

protected override void Dispose(bool disposing)
{
      b.Dispose();
      base.Dispose(disposing);
}
于 2012-04-21T16:47:35.380 回答
1

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

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

  • 由于您提到使用延迟加载(我将在服务器端完全切换的功能),因此您的所有数据库迟早都会被放入内存中(上下文级实体缓存)
  • 您的实体实例将在请求和线程之间共享(是的,对于写操作为真)
  • EntitySet/DbSet 几乎是线程安全的
  • 您的写入操作将完全缓慢且不可预测,因为您将无法保存“仅您的更改”您将保存自上次保存/提交更改以来更改的所有内容,并且您可能还会保存其他线程半生不熟的实体

EF 上下文是 IDisposable 有一个很好的理由:它有望用于紧凑、简短的操作,是的:您应该一直使用 using(...) “事物”。

如果您正在构建一个多人使用的网站、内联网解决方案等,上述所有内容只是一个问题。

于 2012-04-21T17:00:26.477 回答
1

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

使用多个对象上下文意味着每个请求使用多个数据库连接,从而导致数据库的额外压力和更慢的整体性能,而且每个对象上下文都不知道由另一个对象上下文跟踪的实体并且可能必须查询数据库再次为其当前状态或必须发出不必要的更新

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

概括:

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

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

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

问候

于 2012-04-21T18:01:39.060 回答
0

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

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

  return View(b.Data);
}
于 2012-04-21T23:36:32.813 回答