Dot-Net

使用 .NETCore 進行 DAL 和連接字元串的依賴注入

  • December 23, 2019

我是 .NETCore 的 DI 模式的新手,我無法將連接字元串連接到我的 DAL。

我通過接受的答案和後續評論遵循了該執行緒中給出的建議。

這是我的基類

public class BaseRepository : IRepository<IDataModel>
{
   private readonly IConfiguration config;

   public BaseRepository(IConfiguration config)
   {
       this.config = config;
   }

   public string GetSQLConnectionString()
   {
       return config["Data:DefaultConnetion:ConnectionString"];
   }

這是繼承基類的儲存庫類的片段

public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
   public PrivacyLevelRepository(IConfiguration config) : base(config) { }
   public void Add(PrivacyLevelDM dataModel)
   {
        ...
   }
}

這是在我的 startup.cs

public void ConfigureServices(IServiceCollection services)
   {
       // Add framework services.
       services.AddMvc();
       services.AddScoped<IRepository<IDataModel>>(c => new BaseRepository(Configuration));
   }

但是,在我的服務層中,儲存庫類的實例化仍然要求將 (IConfiguration config) 作為參數傳遞。

PrivacyLevelRepository repo = new PrivacyLevelRepository();

如何將 IConfiguration 直接載入到我的 DAL,而不必從 Controller > BLL > DAL 傳遞它。這似乎效率極低,而且不正確。因為 DAL 應該確定對象的連接,而不是控制器或服務層。他們應該不知道數據源,不是嗎?

我認為這很簡單,我只是在 DI/IoC 範式中看不到,但我無法弄清楚。

編輯:我沒有使用實體框架,而是自定義數據層。

感謝任何幫助。

您可以使用配置框架遵循選項模式。這允許您定義一個自定義類型來保存您的配置設置(靜態類型),同時僅限於您的實際相關配置。

你可以像這樣使用它:

public void ConfigureServices(IServiceCollection services)
{
   // register the `Data:DefaultConnection` configuration section as
   // a configuration for the `DatabaseOptions` type
   services.Configure<DatabaseOptions>(Configuration.GetSection("Data:DefaultConnection"));

   // register your database repository
   // note that we don’t use a custom factory where we create the object ourselves
   services.AddScoped<IRepository<IDataModel>, BaseRepository>();
}

這假設一個DatabaseOptions像這樣的類型:

public class DatabaseOptions
{
   public string ConnectionString { get; set; }
}

然後,您可以將其DatabaseOptions註入您的BaseRepository

public class BaseRepository
{
   private readonly DatabaseOptions _options;

   public BaseRepository(IOptions<DatabaseOptions> databaseOptions)
   {
        _options = databaseOptions.Value;
   }
}

當然,如果你有 that 的子類型BaseRepository,你也需要註冊它們並將選項傳遞給基類:

// register the repository as well in the `ConfigureServices` method
services.AddScoped<PrivacyLevelRepository>();
public class PrivacyLevelRepository : BaseRepository, IRepository<PrivacyLevelDM>
{
   public PrivacyLevelRepository(IOptions<DatabaseOptions> databaseOptions)
       : base(databaseOptions)
   { }
}

我像往常一樣實例化和使用 repo。我不確定如何使用我沒有實例化的類。我如何讓這個對象知道它取決於PrivacyLevelRepository

PrivacyLevelRepository repo = new PrivacyLevelRepository();
returnValue = repo.GetAllByDomainID(DomainID).ToList();
return returnValue;

您似乎還不了解依賴注入背後的想法。依賴注入及其基本原理控制反轉簡單地說是避免使用new創建對象。您不是主動依賴實現(在您的範例中為PrivacyLevelRepository),而是放棄了責任,只依賴外部系統為您提供所需的依賴項。

因此,您不是創建一個新的PrivacyLevelRepository,而是注入一個由其他地方創建的實例。這會在您的依賴項的實現上鬆散耦合。一個非常實際的例子是如何PrivacyLevelRepository依賴IOptions<DatabaseOptions>. 作為該儲存庫的消費者,您不需要關心如何獲取這樣的對象來創建儲存庫實例。您甚至不需要知道如何首先創建儲存庫實例。

因此,您的使用者PrivacyLevelRepository應該遵循與儲存庫本身相同的想法:儲存庫不知道如何獲取這些數據庫選項;它只依賴於構造實體來傳遞這樣的對象。你的消費者,我假設一個控制器,應該做同樣的事情:

public class MyController
{
   private readonly PrivacyLevelRepository _privacyLevelRepository;

   public MyController(PrivacyLevelRepository privacyLevelRepository)
   {
        // instead of *creating* a repository, we just expect to get one
        _privacyLevelRepository = privacyLevelRepository;
   }

   public IActionResult SomeRoute()
   {
        var domainId = "whatever";
        var data = _privacyLevelRepository.GetAllByDomainID(domainId).ToList();
        return View(data);
   }
}

當然,必須在某些時候創建依賴項。但是,如果您完全接受依賴注入(ASP.NET Core 不僅非常容易,而且還主動要求您這樣做才能完全工作),那麼您就不需要關心這部分了。您只需在ConfigureServices方法中註冊類型,然後期望依賴項在您需要的地方得到滿足。

有關更多資訊,您絕對應該查看文件的依賴注入章節

引用自:https://stackoverflow.com/questions/43058497