簡體   English   中英

如何配置EF Core連接上下文以解耦程序包依賴關系?

[英]How to configure EF Core connection context to decouple packages dependencies?

我制作了一個使用Entity Framework Core處理持久性的庫。 面向SQL Server數據庫的Web API使用它。 此外,我針對SQLite數據庫進行了測試(單元測試)。

我使用配置文件以一種直接的方式完成了該任務。 因此,在擴展DBContext的類中,我使用以下內容實現了OnConfiguring:

if(isSqlServer) //don't mind where it comes from, it works fine
    optionsBuilder.UseSqlServer(connectionString);
else
    optionsBuilder.UseSqlite(connectionString);

似乎工作正常,但效果不理想。 假設我有這個項目:

  1. 持久層
  2. PersistenceLayerTests
  3. 的WebAPI

由於UseSqlite方法是Microsoft.EntityFrameworkCore.Sqlite包的類中的靜態擴展方法,並且類似地,UseSqlServer方法是Microsoft.EntityFrameworkCore.SqlServer包的類中的靜態擴展方法,有兩件事使我感到困擾。

首先,我必須在三個項目中包括兩個依賴項,以避免在運行時出現錯誤“ System.IO.FileNotFoundException:無法加載文件或程序集Microsoft.EntityFrameworkCore.SqlServer(...)”。

其次,如果需要支持新的DBMS(Oracle,MySQL),則必須在這三個項目中包括新的依賴項。

我希望建立一個方案,其中項目PersistentLayer將不具有那些依賴關系,而PersistentLayerTests將僅依賴於Microsoft.EntityFrameworkCore.Sqlite,而WebAPI將僅依賴於Microsoft.EntityFrameworkCore.SqlServer。

還有另一種方法來配置連接上下文以解耦這些程序包依賴性嗎?

筆記:

  1. 我使用NHibernate做到了這一點,后者為每個DBMS使用不同的驅動程序實現。
  2. 我嘗試使用反射,但效果不佳,並且我發現如果擴展方法具有不同的參數,它將無法正常工作。
  3. 我不需要完整的解決方案。 如果有人可以用另一種方式指出我,那將非常有幫助。

你只需要讓你的DbContext的用戶(PersistenceLayerTests和的WebAPI項目)負責配置,而不是它的的DbContext本身。

DbContext 提供了一個接受DbContextOptions 的構造 函數 您需要公開此構造函數:

public class MyDbContext : DbContext
{
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }

    // ...
}

然后,您可以執行以下操作:

var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();

if (isSqlServer) //don't mind where it comes from, it works fine
    optionsBuilder.UseSqlServer(connectionString);
else
    optionsBuilder.UseSqlite(connectionString);

using (var context = new MyDbContext(optionsBuilder.Options))
{
    // ...
}

這似乎有些矯kill過正,但是在這種情況下,基本策略是放置一個公共界面,並將其分隔在不同的項目中。 不知道這是否是這種情況的最佳解決方案。

然后,不同的項目是獨立的(除了通用界面之外),並且很容易隨時間擴展。

關鍵部分是,在您的主項目中,僅引用接口組件,而不引用其中之一。 如果要避免FileNotFoundException則必須在運行時加載混凝土(裝配體):此外:您需要一種機制來選擇合適的模型(通常稱為factory

讓我們考慮一下其中有3種(sql,sqllite和oracle)的情況:

首先要做的是創建一個公共接口以與適當的Db enginge通信,例如:

//separate assembly
public interface IDbEningeSelector
{
    //added the option builder for simplicity: one could do better.
    void Configure(string connectionString,IOptionsBuilder optionsBuilder);
}

接下來,僅針對具體實現創建3個單獨的項目,一個sql-lite,一個sql和一個oracle。

下一步:在三個項目中創建一個實現此目的的類:

//3 of these.
public class SqlEnging : IDbEngineSelector
{
    public void Configure(string connectionString,IOptionsBuilder optionsBuilder)
    {
         optionsBuilder.UseSqlServer(connectionString);
    }
}

好的,現在您可以選擇其中之一。

//the "thing"
IDbEngineSelector selector = null;

selector = //resolve through factory, possibly based on a flag. 

selector.Configure(connectionString, optionsBuilder);

基本上,您已經完成了可擴展的,動態引用的數據庫提供程序系統。

對於動態程序集解析器,您需要按照本文中的描述進行加載: https : //www.codeproject.com/Articles/1194332/Resolving-Assemblies-in-NET-Core

這實際上將在運行時加載依賴項,為此目的,我建議保留一個特殊路徑以放置這些程序集。

我省略了工廠實現的詳細信息,我需要首先檢查在.net Core中執行此操作的正確方法,繼續...

暫無
暫無

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

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