将DBContext的单个实例保留在应用程序范围内,PRISM& Unity IoC

时间:2017-08-07 22:18:11

标签: c# wpf mvvm unity-container prism

好的,我是DI&利用IoC容器。我正在写一个Prism& WPF的Unity应用程序。

我想实例化一个多个DBContexts的实例,并将其传递给每个使用它的viewmodel。我故意遗漏了一个Repository类,因为我觉得来自EF的CRUD就足够了,只有我在这个应用程序上工作。

我知道我可以在每个ViewModel中初始化DBContext,但是我会有多个有时相同DBContext的实例,我觉得这是一个不好的做法,会有很大的开销。

过去几天我用谷歌搜索了这一点,发现自己有点困惑。

我们将非常感谢您的指导。

3 个答案:

答案 0 :(得分:1)

因此直接的答案是,大多数(可能是所有)DI容器都支持在注册该对象时指定对象生命周期的能力。通常,这可以通过注册单例实例或注册类型并指定它具有“应用程序”生命周期来完成,即对象在应用程序的整个生命周期中都存在。

话虽如此,您通常不希望您的Entity Framework上下文具有应用程序生命周期。

  

我觉得这是一种不好的做法,会产生很大的开销。

实际上,情况正好相反 - 只有在必要时,您的EF上下文才会被视为最佳实践。根据{{​​3}},与构建上下文模型相关的开销应该是最小的:

  

发现模型,处理数据注释和应用流畅的API配置需要花费一些成本。为了避免每次实例化派生的DbContext时产生此成本,在第一次初始化期间缓存模型。每次在同一AppDomain中构造相同的派生上下文时,都会重新使用缓存的模型。可以通过在OnModelCreating方法中将ModelBuilder上的CacheForContextType属性设置为'false'来关闭模型缓存。

再次Microsoft(强调我的):

  

实体框架的上下文旨在用作短期实例,以提供最佳的性能体验。预期上下文将是短暂的并且被丢弃,因此已经实现了非常轻量级并且尽可能地重新使用元数据。在Web方案中,重要的是要记住这一点,并且不要有超过单个请求持续时间的上下文。 同样,在非Web方案中,应根据您对实体框架中不同级别的缓存的理解来丢弃上下文。一般来说,应该避免在应用程序的整个生命周期中使用上下文实例,以及每个线程和静态上下文的上下文。

事实上,创建一个适用于应用程序整个生命周期的上下文可能会有问题,因为here会导致您的上下文变得非常大:

  

默认情况下,在查询结果中返回实体时,就在EF实现它之前,ObjectContext将检查具有相同键的实体是否已加载到其ObjectStateManager中。如果具有相同键的实体已存在,则EF将其包含在查询结果中。虽然EF仍会针对数据库发出查询,但这种行为可以绕过实体多次实现的大部分成本。

object caching

  

使用ObjectContext的次数越多,通常越大。这是因为它拥有对其所知的所有实体的引用,基本上是您查询,添加或附加的任何实体。所以你应该重新考虑无限期地共享同一个ObjectContext

你说:

  

我知道我可以在每个ViewModel中初始化DBContext,但是我会有多个实例,有时候会有相同的DBContext。

我认为如果你的ViewModel存在很长时间,那么将你的DBContext限定为ViewModel的生命周期可能仍然太长(由于对象缓存)。最好的方法是识别ViewModel中的工作单元,并将DBContext的生命周期作为范围。

另一种选择是禁用对象缓存。

答案 1 :(得分:0)

将IoC中的生命周期类型设置为Singleton以解析DBContext。然后每次调用Resolve()时,您将获得相同的DBContext实例。我还没试过这个,但这是一个让你入门的想法。也许在C#中读一下对象生命周期。

在Unity中,我认为它看起来像这样:

    var container = new UnityContainer();
container.RegisterType(typeof(IMyInterface), 
                       typeof(MyImplementation), 
                       "singletonReg", 
                        new ContainerControlledLifetimeManager());

答案 2 :(得分:0)

覆盖你的boostrapper类的ConfigureContainer()方法并调用RegisterInstance的{​​{1}}方法:

Container

然后,您可以像往常一样解决上下文的唯一实例:

protected override void ConfigureContainer()
{
    base.ConfigureContainer();
    Container.RegisterInstance(new YourDbContext());
}