通过WebApi 2.0中的Microsoft Unity为每个请求提供Instanciate Entity Framework上下文

时间:2016-08-17 17:14:59

标签: entity-framework concurrency asp.net-web-api2 unity-container

我有一个在我的开发环境中正常工作的N层解决方案。显然它也适用于生产环境,但有时执行失败。我不懂为什么。我只知道数据库没有任何变化,没有看到有用的错误,也没有写入日志。 我的假设是一个并发问题。我认为,一旦初始化实体框架上下文,当我尝试做多个选择时,某些事情就会失败。

这里我的解决方案是如何构建的

enter image description here

在外观中我注入了实体框架上下文。这里是我的web.config服务接口的配置:

<containers>
  <container>
    <types>
      <register type="it.MC.IContext.IDataContext, IContext"
                mapTo="it.MC.EntityFrameworkContext.PublicAreaContext, EntityFrameworkContext">
        <lifetime type="singleton" />        
      </register>

      <register type="it.MC.IFacade.IPublicAreaFacade, IFacade"
                mapTo="it.MC.Facade.PublicAreaFacade, Facade">
        <interceptor type="TransparentProxyInterceptor" />
        <lifetime type="singleton" />
        <constructor>
          <param name="context" type="it.MC.IContext.IDataContext, IContext"/>
        </constructor>
      </register>
    </types>
  </container>
</containers>

如您所见,我的背景和外观是单身。我认为两者都是错的。我认为Facade实体Framewrk上下文应该是每个请求都是instanciate。我认为这也将解决并发问题。

有人可以帮我纠正我的代码吗?

谢谢

1 个答案:

答案 0 :(得分:1)

我知道你的问题是:

  

有人可以帮我纠正我的代码吗?

我这样读了:

  

任何人都可以帮我更改此代码,以便每次请求重新初始化IContextIFacade

有了这样说......是的,我也怀疑你想让你的IContext成为一个单身人士。

Why you shouldn't use singleton DataContexts in Entity Framework

如果这就是您想要的,那么您可以将生命周期管理者更改为PerRequestLifetimeManager。请注意,您可能需要Unity.Mvc NuGet包。

<containers>
  <container>
    <types>
      <register type="it.MC.IContext.IDataContext, IContext"
                mapTo="it.MC.EntityFrameworkContext.PublicAreaContext, EntityFrameworkContext">
        <lifetime type="Microsoft.Practices.Unity.PerRequestLifetimeManager, Microsoft.Practices.Unity.Mvc" />        
      </register>

      <register type="it.MC.IFacade.IPublicAreaFacade, IFacade"
                mapTo="it.MC.Facade.PublicAreaFacade, Facade">
        <interceptor type="TransparentProxyInterceptor" />
        <lifetime type="Microsoft.Practices.Unity.PerRequestLifetimeManager, Microsoft.Practices.Unity.Mvc" />
        <constructor>
          <param name="context" type="it.MC.IContext.IDataContext, IContext"/>
        </constructor>
      </register>
    </types>
  </container>
</containers>

在投入制作之前,我建议您阅读this post关于PerRequestLifetimeManager

的内容
  

其目的是仅为每个请求实例化一个实例,   这可能(例如)防止冗余操作和查找   在一次请求过程中。

     

危险在于,如果有人认为创建的对象是好的   在请求期间存储状态的地方。依赖的想法   注入是一个类接收依赖(通常是一个   界面)并且不知道&#34;关于它的任何事情,除了它   实现该接口。

另外,请考虑一下Facade,以及如果重新启动每个请求,它将如何运作。它是否在初始化时执行任何繁重的操作?您可能想要考虑那个人的终身经理。

<强>更新 由于您使用的是WebAPI,因此您应该能够使用HierarchicalLifetimeManager

http://www.asp.net/web-api/overview/advanced/dependency-injection

  

附加到HttpConfiguration对象的依赖项解析器具有   全球范围。当Web API创建控制器时,它会调用BeginScope。   此方法返回表示子范围的IDependencyScope。

     

Web API然后在子范围上调用GetService来创建   控制器。请求完成后,Web API将调用Dispose   儿童范围。使用Dispose方法处理控制器   的依赖关系。

http://www.devtrends.co.uk/blog/introducing-the-unity.webapi-nuget-package

  

如果您要注册任何实现IDisposable的组件,请执行此操作   作为实体框架的DbContext,您需要确保这些   组件在请求结束时被处理掉。这是实现的   通过使用HierarchicalLifetimeManager注册这些组件。