簡體   English   中英

在應用程序范圍,PRISM和Unity IoC中保持單個DBContext實例

[英]Keeping a single instance of DBContext in application scope, PRISM & Unity IoC

好的,我是DI和使用IoC容器的新手。 我正在為WPF編寫Prism&Unity應用程序。

我想實例化一個以上DBContexts的實例,並將其傳遞給使用它的每個視圖模型。 我故意省略了一個Repository類,因為我覺得EF的CRUD足夠了,而且只有我在處理此應用程序。

我知道我可以在每個ViewModels中初始化DBContext,但是那時我將有多個實例,有時是同一個DBContext,這似乎是一種不好的做法,並且會產生大量開銷。

在過去的幾天里,我用谷歌搜索了一下,發現自己更加困惑。

您的指導將不勝感激。

因此,直接的答案是,大多數(也許所有)DI容器都支持在注冊對象時指定對象生存期的功能。 通常,這可以通過注冊單例實例或注冊類型並指定其具有“應用程序”生存期來完成,即對象在應用程序的整個生存期內都存在。

話雖這么說,您通常不希望實體框架上下文具有應用程序生存期。

我覺得這是一種不好的做法,並且會產生大量開銷。

實際上,情況恰恰相反-EF環境被認為是最佳實踐,它僅在必要時才存在。 根據Microsoft的說法,與構建上下文模型相關的開銷應最小:

發現模型,處理數據注釋和應用流利的API配置涉及一些成本。 為了避免在每次實例化派生的DbContext時產生此成本,模型將在第一次初始化期間進行緩存。 每次在相同的AppDomain中構造相同的派生上下文時,都會重新使用緩存的模型。 可以通過在OnModelCreating方法中將ModelBuilder上的CacheForContextType屬性設置為“ false”來關閉模型緩存。

並再次在這里 (重點煤礦):

實體框架的上下文旨在用作短期實例,以提供最佳的性能體驗。 預期上下文將短暫存在並被丟棄,因此上下文已實現為非常輕量級,並在可能的情況下重新使用元數據。 在Web場景中,請記住這一點,並且不要讓上下文超出單個請求的持續時間,這一點很重要。 同樣,在非Web場景中,應根據您對實體框架中不同緩存級別的理解,丟棄上下文。 一般來說,應該避免在應用程序的整個生命周期中都具有上下文實例 ,以及每個線程的上下文和靜態上下文。

實際上,由於對象緩存可能會導致上下文變得非常大,因此創建一個在應用程序的整個生命周期中都存在的上下文可能會出現問題:

默認情況下,當實體在查詢結果中返回時,就在EF實現它之前,ObjectContext將檢查具有相同鍵的實體是否已加載到其ObjectStateManager中。 如果已經存在具有相同鍵的實體,則EF會將其包括在查詢結果中。 盡管EF仍然會針對數據庫發出查詢,但是這種行為可以繞開多次實現實體的許多成本。

另外

使用ObjectContext的次數越多,通常它得到的越大。 這是因為它引用了它所知道的所有實體,基本上是您查詢,添加或附加的任何實體。 因此,您應該重新考慮無限期共享相同的ObjectContext

你說:

我知道我可以在每個ViewModels中初始化DBContext,但是那時我將有多個實例,有時是同一DBContext。

我會爭辯說,如果您的ViewModels壽命很長,那么將DBContext限定為ViewModel的生命可能仍然太長(由於對象緩存)。 最好的方法是在ViewModel中確定工作單​​元,並將DBContext的生命范圍限制在這些范圍內。

另一種選擇是禁用對象緩存。

在IoC中將生存期類型設置為Singleton以解決DBContext。 然后,每次調用Resolve()時,您將獲得相同的DBContext實例。 我還沒有嘗試過,但這是一個讓您入門的想法。 也許讀了一些關於C#中對象生存期的信息。

在Unity中,我認為它看起來像這樣:

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

重寫boostrapper類的ConfigureContainer()方法,並調用ContainerRegisterInstance方法:

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

然后,您可以照常解析上下文的唯一實例:

var context = _container.Resolve<YourDbContext>();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM