簡體   English   中英

跨項目的 EF Core 數據上下文注入

[英]EF Core Data Context injection across Projects

我有一個項目 A,它是一個 class 庫和項目 B,它使用 A。項目 A 是一個可以跨項目(例如 B)使用的通用幫助程序庫。

EF Core 數據上下文和數據實體需要在項目 B 中定義(因為它們可能因項目而異),但我需要將數據上下文注入到項目 A 中服務類的構造函數中(以通用方式處理所有內容)。 在 Project BI 中有數據上下文

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

        public DbSet<Test> Tests { get; set; }

    }

在項目 AI 中有實現 IUnitOfWork 的 class UnitOfWork。 在它的構造函數中,我需要注入數據上下文。 但是,由於項目 A 不能引用項目 B(項目 A 是通用的),我不能在參數列表中使用數據上下文的實際名稱。 由於datacontext繼承自DbContext,我試過了

public UnitOfWork(DbContext dc){...}

在項目 B 的啟動中,我有

services.AddDbContext<MyDataContext>(options =>
     {
          options.UseSqlServer("...<the connection string> ...");
     });
services.AddScoped<IUnitOfWork, UnitOfWork>();

一切都可以編譯,但在運行時需要創建 UnitOfWork 時,出現錯誤

System.AggregateException: Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: IUnitOfWork Lifetime: Scoped ImplementationType: UnitOfWork': Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'UnitOfWork'.)

內部例外是

InvalidOperationException: Unable to resolve service for type 'Microsoft.EntityFrameworkCore.DbContext' while attempting to activate 'UnitOfWork'.

任何幫助都深表感謝。

編輯我被要求在評論中提供 UnitOfWork class 詳細信息。 所以這里

public class UnitOfWork : IUnitOfWork
    {
        private readonly DbContext dc;
        private readonly IServiceProvider serviceProvider;

        public UnitOfWork(DbContext dc, IServiceProvider serviceProvider)
        {
            this.dc = dc;
            this.serviceProvider = serviceProvider;
        }
        public void BeginTransaction()
        {
            dc.Database.BeginTransaction();
        }

        public void BeginTransaction(IsolationLevel isolationLevel)
        {
            dc.Database.BeginTransaction(isolationLevel);
        }

        public void CommitTransaction()
        {
            dc.Database.CommitTransaction();
        }

        public void RollbackTransaction()
        {
            dc.Database.RollbackTransaction();
        }

        public bool IsTransactionActive()
        {
            return dc.Database.CurrentTransaction != null;
        }

        public async Task<bool> SaveAsync()
        {
            return await dc.SaveChangesAsync() > 0;
        }

        public bool Save()
        {
            return dc.SaveChanges() > 0;
        }

    }

您的UnitOfWork服務依賴於DbContext類型,而不是注冊到 DI 的派生MyDataContext類型。 所以你有兩個選擇:

您可以像這樣修改 UnitOfWork 注冊(告訴 IoC 容器使用 MyDataContext 實例化 UnitOfWork):

services.AddScoped<IUnitOfWork>(srp => new UnitOfWork(srp.GetRequiredService<MyDataContext>(), srp));

或者您也可以將DbContext注冊到 DI 中,因此 DI 容器知道當有人請求 DbContext 時它應該返回 MyDbContext:

services.AddScoped<DbContext, MyDataContext>();

請注意,您的UnitOfWork class 中似乎未使用ServiceProvider字段。

解決方案是進行兩項更改。 首先是按照@fbede 的建議顯式注冊服務

services.AddScoped<DbContext, MyDataContext>();

現在,當我們這樣做時,我們失去了通過AddDbContext Extension 方法設置DbContextOptionsBuilder選項的便利性。

所以我們需要重寫datacontext中的OnConfiguring方法來設置我們需要的配置選項。 例如:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(configuration.GetConnectionString(<key>));
    }

當然, IConfiguration是在MyDataContext構造函數中注入的

暫無
暫無

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

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