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

dev*_*xer 49 asp.net-mvc entity-framework ef-code-first entity-framework-4.1 asp.net-mvc-3

如果这已经得到回答,请道歉,但如果您不使用IOC容器,如何保证每个请求有一个Entity Framework DbContext?(到目前为止,我遇到的答案涉及IOC容器解决方案.)

似乎大多数解决方案都挂钩到HttpContext.Current.Items字典中,但是如何在请求完成时保证处理DbContext?(或者EF的处理不是绝对必要的DbContext吗?)

编辑

我目前正在我的控制器中实例化和处理我的DbContext,但我在ActionFilters和我的MembershipProvider中也有几个单独的DbContext实例(我刚注意到,也有几个验证器).因此,我认为集中我的DbContext的实例化和存储以减少开销可能是个好主意.

wal*_*her 73

我知道这不是最近的一个问题,但无论如何我都会发布我的答案,因为我相信有人会觉得它很有用.

可能很多其他人,我按照接受的答案中提到的步骤.是的,它有效.但是,有一个问题:

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

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

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;
          }
      }
 }
Run Code Online (Sandbox Code Playgroud)

然后进行处置

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

此修改可确保您仅在每个请求时仅在需要时实例化和处置上下文一次.选定的答案每次都会实例化上下文.

注意: DB1Entities派生自DbContext(由VS生成).你可能想用你的上下文名称改变它;)

注2:在这个例子中,我只使用一个dbcontext.如果您需要使用多个,则需要根据需要修改此代码.不要把它作为世界问题的最终解决方案,因为它肯定不是最终产品.它只是为了提示,如何以一种非常简单的方式实现它.

注3:同样的方法也可以在不同的情况下使用,例如,当您想要共享SqlConnection的实例或任何其他...时,此解决方案不是DbContext对象,也不是Entity框架.

  • 我想使用该解决方案,但我在解决方案中有另一个项目来处理数据库访问,所以我不能使用HttpContext.有什么办法可以实施你的建议吗? (2认同)

Cha*_*ran 60

我会使用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();
}
Run Code Online (Sandbox Code Playgroud)

在你的EntityContext类中......

public class EntityContext
{
    public static EntityContext Current
    {
        get { return HttpContext.Current.Items["_EntityContext"] as EntityContext; }
    }
}
Run Code Online (Sandbox Code Playgroud)


Dar*_*rov 10

一种方法是订阅Application_BeginRequest事件,将DbContext注入当前的HttpContext以及Application_EndRequest从HttpContext和dispose中获取.介于两者之间的任何东西(几乎所有东西:-))都可以从当前的HttpContext中获取DbContext并使用它.而且,是的,你应该处理它.顺便说一下,你有没有理由不使用已经为你做过的DI框架以及其他有用的东西?

  • 如果您的应用程序很简单也没关系.它具有前瞻性.立即设置*虽然它很简单,但随着你的应用变得越来越大,你需要它时会更容易.当然,除非你的应用程序保持小规模. (2认同)

Dru*_*der 7

Chad Moran的小补充回答.它受到沃尔特笔记的启发.为了避免静态内容的上下文初始化,我们应该检查当前的路由处理程序(这个例子仅适用于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();
  }
}
Run Code Online (Sandbox Code Playgroud)