簡體   English   中英

EF6 DbContext IOC依賴

[英]EF6 DbContext IOC Dependency

我在Windows服務/控制台應用程序中使用EF6。 我已經為我的業務層接口和實現成功實現了IOC / DI。 使用構造函數注入。 我也在使用對象數據庫,任務並行庫。 為了更好的表現,我很高興。

還使用System.IO.Abstractions使我的代碼更易於測試。

EF6使用.tt文件為所有域實體創建POCO clases,非常方便。 為了執行數據庫查詢,我寫的每一個地方

using(var db = new MyContext())
{
// code reading from/writing to database
...
...
}

我知道這不是正確的做法,並在我的代碼中的各個地方發出噪音。 我想讓它松散耦合。 現在我的數據庫操作 - 我很困惑如何前進,使它更可測試和松散耦合..任何人都可以指出一個很好的例子,可以參考的文章。

我想要實現的兩個主要方面是對連接字符串配置(對於各種服務器部署)有更多的控制, DbContext在我的代碼中非常松散地耦合。

要解決分離(和測試)問題,您可以為DbContextIMyDbContext )創建自己的接口,並重新公開所有類型化的實體DbSetsSaveChanges()以及可能的其他一些方法。 您還應該使此接口為Disposable

public interface IMyDbContext : IDisposable
{
    IDbSet<Foo> Foos { get; set; }
    IDbSet<Bar> Bars { get; set; }

    int SaveChanges();
    DbEntityEntry<T> Entry<T>(T entity) where T : class;
}

(您也可以考慮接口的只讀和讀寫版本)

然后更改具體的DbContext以實現此接口。 您現在可以合理地與DbContext (用於單元測試等)分離,但仍然可以訪問IQueryable的有用性,固有工作單元和DbContext提供的緩存。

然后,這里有兩個選項,用於將IMyDbContext注入到您的業務/服務類中

  1. 構造函數注入IDbContext

要么

  1. 創建一個Factory方法和一個Factory接口,用於創建具體的DbContext ,然后對IMyDbContextFactory工廠接口進行構造函數注入(您將需要接口,而不是具體工廠,再次用於模擬測試目的)。

這里的選擇取決於您需要對DbContext執行的DbContext 在IoC容器中配置#1可能很棘手,因為您需要將生命周期管理移交給容器。 但是,如果可以為每個請求配置新實例,那么這在Web應用程序中可能是有益的,因此如果請求(假設單個線程)可以將其用作緩存。

我個人更喜歡#2,因為這允許直接管理上下文:

using(var db = _myContextFactory.CreateDB())
{
    db.SaveChanges();
}

但顯然,我們失去了長期環境(如緩存)的任何潛在好處。 但是,如果需要,還有許多其他替代技術可用於緩存。

需要注意的是: DbContext根本不是線程安全的 - 如果你使用的是TPL,請確保每個任務都獲得自己的DbContext實例 - 例如,使用Parallel.For / ForEachlocalinit重載來使用它時實例化它。

暫無
暫無

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

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