ASP.NET MVC中每个请求一个DbContext(没有IOC容器)

道歉,如果这已经被回答,但如何保证一个entity frameworkDbContext每个请求,如果你不使用国际奥委会容器? (到目前为止,我所遇到的答案涉及国际奥委会容器解决scheme。)

看起来像大多数解决scheme挂钩到HttpContext.Current.Items字典,但如何保证在请求完成时处理DbContext? (或者是用EF DbContext来处理不是绝对必要的?)

编辑

我目前在我的控制器实例化和处置我的DbContext,但我也有我的DbContext在ActionFilters和我的MembershipProvider(我刚刚注意到,也是一对夫妇validation器)的几个单独的实例化。 所以,我认为集中实例化和存储我的DbContext以减less开销可能是一个好主意。

我将使用BeginRequest / EndRequest方法,这有助于确保在请求结束时正确处理上下文。

 protected virtual void Application_BeginRequest() { HttpContext.Current.Items["_EntityContext"] = new EntityContext(); } protected virtual void Application_EndRequest() { var entityContext = HttpContext.Current.Items["_EntityContext"] as EntityContext; if (entityContext != null) entityContext.Dispose(); } 

并在您的EntityContext类…

 public class EntityContext { public static EntityContext Current { get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; } } } 

我知道这不是一个最近的问题,但我会张贴我的答案无论如何,因为我相信有人可能会觉得它有用。

和其他很多人一样,我遵循了被接受的答案中提到的步骤。 是的,它的工作。 但是 ,有一个问题:

方法BeginRequest()和EndRequest() 每次发出请求时都会触发 ,但不仅仅是aspx页面,而是所有的STATIC CONTENT! 也就是说,如果你使用上面提到的代码,并且在你的页面上有30个图像,那么你将重新实例化你的dbcontext 30次!

解决scheme是使用包装类来检索上下文,如下所示:

 internal static class ContextPerRequest { internal static DB1Entities Current { get { if (!HttpContext.Current.Items.Contains("myContext")) { HttpContext.Current.Items.Add("myContext", new DB1Entities()); } return HttpContext.Current.Items["myContext"] as DB1Entities; } } } 

然后处理

 protected void Application_EndRequest(object sender, EventArgs e) { var entityContext = HttpContext.Current.Items["myContext"] as DB1Entities; if (entityContext != null) entityContext.Dispose(); } 

此修改可确保您仅在每个请求中实例化和处理您的上下文,并且仅在需要时才处理。 所选答案每次都会实例化上下文。

注意: DB1Entities是从DbContext派生的(由VS生成)。 你可能会想要改变你的上下文名称;)

注2:在这个例子中,我正在使用一个dbcontext。 如果你需要使用多个,你需要根据你的需要修改这个代码。 不要把这看作是世界问题的最终解决scheme,因为它当然不是最终产品。 它只是为了提供一个提示,如何以一种非常简单的方式来实现。

注3:同样的方法也可以在不同的情况下使用,例如当你想共享一个SqlConnection的实例或其他的…这个解决scheme不是排他性的DbContext对象,也不是entity framework。

一种方法是订阅Application_BeginRequest事件,将DbContext注入到当前的HttpContext中,并在HttpContext的Application_EndRequest提取并处理。 之间的任何东西(这几乎是一切:-))可以从当前的HttpContext获取DbContext并使用它。 而且,是的,你应该处置它。 顺便说一下,有没有什么原因,你不使用一个DI框架已经为你做了这些其他有用的东西吗?

乍得莫兰答案的小增加。 它受到了Walther笔记的启发。 为了避免静态内容的上下文初始化,我们应该检查当前的路由处理器(这个例子只适用于MVC):

 protected virtual void Application_BeginRequest() { var routeData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(this.Context)); if (routeData != null && routeData.RouteHandler is MvcRouteHandler) { HttpContext.Current.Items["_EntityContext"] = new EntityContext(); } } 

如果在控制器中实现了IDisposable,并在处理方法中configuration上下文,并在控制器构造函数中实例化新的上下文,则应该为每个请求实例化控制器以确保安全。 但是,我不明白为什么要这么做? …您应该使用DI,或使用一个静态的上下文实例来创build上下文工厂。 如果您不使用一个实例(您为每个请求创build一个实例),那么在某个时刻您将遇到问题。 未定义上下文的问题是EF在上下文中caching数据,如果上下文的某个其他实例更改了已经在另一个上下文中caching的数据库中的某些内容,则说明存在不一致的状态。 在DI变得如此stream行之前,我曾经在应用程序的某个地方使用了一个静态的上下文实例,比起每个请求创build自己的上下文要快很多,但是你需要实现状态检查代码,以确保上下文连接数据库是好的…有这个问题有很多更好的解决scheme,最好是使用一些DI框架。 我会推荐Ninject与MVCTurbine结合使用,这很容易设置,你可以通过NuGet添加它。

这里的滑坡处于不一致的状态。 如果您的应用将拥有多个用户,并且他们有可能同时更改数据,那么如果保留单个上下文,则可能会开始遇到数据完整性问题。