【问题标题】:Instanciate Entity Framework context per request via Microsoft Unity in WebApi 2.0通过 Web Api 2.0 中的 Microsoft Unity 实例化每个请求的实体框架上下文
【发布时间】:2016-08-17 17:14:59
【问题描述】:

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

这里是我的解决方案的结构

在外观中,我注入了实体框架上下文。这里是我的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>

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

谁能帮我更正我的代码?

谢谢

【问题讨论】:

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


    【解决方案1】:

    我知道你的问题是:

    谁能帮我更正我的代码?

    我是这样读的:

    谁能帮我更改此代码,以便根据请求重新初始化 IContextIFacade

    话虽如此...是的,我也怀疑您是否希望将IContext 保留为单身人士。

    Why you shouldn't use singleton DataContexts in Entity Framework

    如果您愿意,可以通过以下方法将lifetimemanager 更改为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

    它的目的是每个请求只实例化一个实例, 这可以(例如)防止冗余操作和查找 在单个请求的过程中。

    如果有人认为创建的对象是好的 在请求期间存储状态的地方。依赖的概念 注入是一个类接收一个依赖项(通常是 接口)并且除了它之外根本不“知道”任何关于它的东西 实现该接口。

    另外,想想你得到的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 注册这些组件。

    【讨论】:

    • 有趣.. 我见过 perRequestLifetimeManager 但我不确定是否是正确的解决方案,因为我需要 unity.mvc 包而我没有 mvc。
    • 我不认为外观有问题,因为它里面的所有初始化都是惰性的。 PerRequestLifrtimeManager 应该不是问题,因为我的后端是无状态的。我只是有一个疑问。在您发送给我的链接中写道:假设有人确定该依赖项的生活方式应该是暂时的,而不是每个 Web 请求。瞬态是什么意思?
    • 瞬态意味着它每次都更新。不是每个请求或单例,而是每次都解决。我也会尝试为 WebApi 寻找资源。
    • 所以在我的情况下,transient 应该与请求一致,因为我解决了每个请求调用一次的外观中的上下文
    • @Ciccio - 是的,在这种情况下瞬态是正确的。您也可以尝试使用PerResolveLifetimeManager,它会在每个解析周期创建一个实例。在你的 dispose 和构造函数中设置一个调试器(或记录它)。然后提出一些请求,您应该会看到它正在被创建和处理。
    猜你喜欢
    • 2013-05-08
    • 1970-01-01
    • 1970-01-01
    • 2010-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 2011-09-28
    相关资源
    最近更新 更多