微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET MVC无IOC容器中的每个请求一个DbContext

如何解决ASP.NET MVC无IOC容器中的每个请求一个DbContext

| 抱歉,如果已解决此问题,但是如果您不使用IOC容器,如何保证每个请求一个Entity Framework DbContext? (到目前为止,我遇到的答案涉及IOC容器解决方案。) 似乎大多数解决方案都挂在
HttpContext.Current.Items
字典中,但是如何确保请求完成后处置DbContext? (或者使用EFѭ1处置是否不是绝对必要的?) 编辑 我目前正在实例化并将DbContext放置在控制器中,但是我在ActionFilters和MembershipProvider中也有几个单独的DbContext实例化(我刚刚注意到,还有两个验证器)。因此,我认为最好集中化DbContext的实例化和存储以减少开销。     

解决方法

        我将使用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页面,而且针对所有静态内容!就是说,如果您使用上面提到的代码,并且页面上有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;
          }
      }
 }
然后处置
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。如果需要使用多个代码,则需要根据需要修改此代码。不要将此作为解决世界问题的最终解决方案,因为它肯定不是最终产品。它只是为了提示如何以一种非常简单的方式实现它。 注意3:同样的方法也可以在不同的情况下使用,例如,当您想共享SqlConnection的实例或任何其他...时,此解决方案不仅限于DbContext对象或Entity框架。     ,        一种方法是订阅
Application_BeginRequest
事件,将DbContext注入当前的HttpContext中,并从HttpContext中的
Application_EndRequest
中获取并进行处理。介于两者之间的任何东西(几乎是所有东西:-)都可以从当前的HttpContext获取DbContext并使用它。而且,是的,您应该处置它。顺便说一句,您有没有理由不使用DI框架,而DI框架已经为您完成了其他有用的工作?     ,        乍得·莫兰(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();
  }
}
    ,        如果您在控制器中实现IDisposable,并在处理方法中处理上下文,并在控制器构造函数中实例化新的上下文,则应该为每个请求实例化控制器,这是安全的。 但是,我看不到为什么要这么做? ... 您应该使用DI,或使用一个静态的上下文实例创建上下文工厂。如果您不使用一个实例(为每个请求创建一个实例),则有时会遇到问题。未处理的上下文的问题在于EF在上下文中缓存数据,并且如果上下文的其他某个实例更改了已在另一个上下文中缓存的DB中的某些内容,则您的状态将不一致。在DI如此流行之前,我曾经在应用程序中的某个位置拥有一个静态的上下文实例,这比让每个请求都拥有自己的上下文要快和安全得多,但是您需要实施状态检查代码以确保该上下文与db的连接是可以的...这个问题有很多更好的解决方案,最好是使用一些DI框架。我建议将Ninject与MVCTurbine结合使用,它很容易设置,您可以通过NuGet添加它。     ,这里的滑坡状态不一致。如果您的应用程序将要有多个用户,并且他们有可能同时更改数据,那么如果您保留一个上下文,则可能会开始遇到数据完整性问题。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。