1

情况:我想要做的是访问页面生命周期的数据上下文。这主要是为了(a)当访问延迟加载的属性时,避免使用()的一系列操作并避免(b)超出视图中的范围异常。MVC 4,EF 4.3在应用程序请求的生命周期中管理上下文

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

我通常做的是

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

在我的控制器或数据层。根据我的阅读,这个很好的一点是它很干净,不会造成内存泄漏等问题。但缺点是,即使是单个页面的生命周期,我也会一次又一次地执行此操作,并且我的对象在因为我已经处理了上下文。

我做了一些阅读,发现一个类似的帖子从2009年,但在答案中没有代码。当然有些人已经找到了如何解决这个 - 我想我必须做一些事情

Application_BeginRequest and EndRequest 

但我只是不知道如何和什么陷阱/最佳实践。

谢谢您的帮助,(有一些代码示例如果可能的话!)

回答

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); 
} 
+0

感谢您可以返回 - 做了仓库的方式快速阅读我认为这对我的应用程序来说可能是一种矫枉过正的现象(至少在这一点上)。但是您的页面级访问上下文的解决方案看起来简单而优雅!我会尝试并回来。 – jeremy 2012-04-21 17:40:03

+0

我添加了一个BaseController,我在一些较小的页面中继承了它,并添加了这些代码。我需要什么! – jeremy 2012-04-21 17:50:25

+0

我之前使用过建议的知识库和工作单元,但过了一段时间后,我放弃了它,因为它太多而且通用性不够。所以我建议你尝试让你自己的解决方案。 – 2012-04-21 18:05:45

1

你想使用你的datacontext是这样的的绝对是一个禁忌(除非你正在处理几百行数据库,在这种情况下为什么是EF)。

但是,如果你有一个真正的生产规模的数据库,牵制的背景下应用范围将导致以下:

  • 既然你提的使用lazyload(一个功能,我会在完全 开关服务器端)迟早你的数据库将 被咕噜咕噜到内存(上下文级别实体缓存)
  • 实体实例将请求和线程(间共享是, 写操作真)
  • 的EntitySet/DbSet几乎都是线程安全的
  • 您的写入操作将会非常缓慢且不可预测,因为您将无法保存“只是您的更改”,您将保存自上次保存/ submitChanges以来 已更改的所有内容,而且您将可能救一个人的其他线程 半烤实体太

的EF上下文是IDisposable的一个很好的理由:它有望在紧凑型,短操作中使用,并且是:你应该在用做( ......)“东西”。

如果您正在构建一个网站,intranet soluton等将被超过一个人使用,上述所有内容都只是一个问题。

+0

彼得 - 如果我是正确的解释,你说我目前的做法是好的(即我使用()并保持上下文很短的时间)。我通过将范围保持在应用程序级别(例如作为一个单例)来理解这些缺点 - 但我并不是建议这样做。为什么在单个页面请求的生命周期中保留上下文并在其最后处置会非常糟糕? – jeremy 2012-04-21 17:17:36

1

先不使用懒加载(实体框架进入到数据库,并带来的结果返回一行一次)的意见,从视图的查询是不好的做法,也导致选择N + 1)选择N + 1是一种数据访问反模式,其中数据库以次优方式访问,)或类似的不良做法。

使用多个对象上下文意味着每个请求使用多个数据库连接,从而导致数据库的额外压力和较慢的整体性能,同时每个对象上下文都不知道其他对象上下文跟踪的实体以及可能需要再次查询数据库以了解其当前状态,或者必须发出不必要的更新

编写视图时,不应该考虑持久性或查看正在生成的查询数。

摘要:

  1. 执行的操作的所有查询。

  2. 部队使用Include方法收集的贪婪加载指定你想要的对象模型件在 初始查询到包括。

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

问候

+0

非常有用的评论,谢谢。我已经开始在动作中加入include()来加载我需要的内容,并且我将上下文限制为每个页面请求1个,或者根据需要使用using()更短。 – jeremy 2012-04-21 20:32:04

0

退出使用块之前这样的背景下将在规模时延迟加载视图

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

    return View(b.Data); 
} 
+0

这只是不正确的。 return关键字在大括号之前的事实并不意味着客户端可以访问所得到的View的时间所处理的上下文... – 2012-04-22 12:32:41

+0

这不起作用。我确信我尝试了这种方式 - 在我可以访问我的视图中的属性之前,上下文会处理掉。 – jeremy 2012-04-25 05:55:04