我有一個 .NET 5 控制臺應用程式,我試圖將其用作 Windows 服務,它現在采用后臺服務的形式。我有所有的依賴注入設定,并且可以很好地處理 appsettings 和日志記錄。今天,我想將我的資料添加到組合中。這是我的應用程式的結構:
我已經完成了 Entity Framework Core
DataContext類。然后我創建了一個包裝器,我將用它來創建我所有的 CRUD 方法并在我的應用程式中使用。這個類名為
DataAccess.然后,我在我的
Program.cs,Main方法中添加了以下內容:services.AddSingleton<DataAccess>(); services.AddDbContext<MyDataContext>(options => options.UseSqlServer(ConnnectionString));最后,在我的
DataAccess包裝類中,我注入了 ,DataContext所以我可以在這里做我的 CRUD 操作。像這樣:public DataAccess(MyDataContext dataAccess) { this.dataAccess = dataAccess; }
當我這樣做并除錯時,我的應用程式啟動時出現以下例外:
無法從單例“ENS.Data.DataAccess”使用范圍服務“ENS.Data.MyDataContext”。
我知道我的DataAccess包裝器是一個單身人士,我認為當你這樣做時services.AddDbContext是有范圍的。所以,我有點理解這個錯誤。我不明白的是我認為你可以從單身人士中消費一個范圍?
我在這里做錯了什么或更好的是,將 Entity Framework Core 設定和注入DataContext到我的應用程式中以供我的DataAccess包裝DataAccess器使用然后我的包裝器在我的整個應用程式中使用的最佳方法是什么?
謝謝!
uj5u.com熱心網友回復:
當您將一個服務注入另一個服務時,您需要仔細考慮這兩個服務的生命周期。如果將服務 A 注入服務 B,則服務 A 的生命周期必須大于或等于服務 B 的生命周期(因為服務 B 將持有對服務 A 的參考,從而阻止垃圾收集器回收分配給服務的記憶體)一種)。
基于此規則,您可以安全地在作用域服務內部注入單例,但不允許相反(因為作用域服務的生命周期比單例服務的生命周期短)。違反此規則會導致一種稱為俘虜依賴的反模式。如果允許將范圍服務注入單例服務,那么范圍服務將成為俘虜依賴項,其生命周期將與單例服務之一一致(換句話說,注入的范圍服務實際上將成為單例服務)。
Microsoft DI 容器顯式檢查此反模式,這就是您在嘗試將作用域服務注入單例服務時收到錯誤的原因。
在您的情況下,您有兩種選擇:
- 避免使用資料訪問包裝器類并在需要的地方直接注入物體框架背景關系
- 維護資料訪問包裝器類并為其賦予范圍或瞬態生命周期,以便您可以將范圍物體框架背景關系注入其中
作為旁注,如果您需要使用托管服務類中的范圍服務,您可以將IServiceScopeFactory服務注入托管服務并使用它來創建范圍并決議范圍服務。
下面是一個例子:
public sealed class MyHostedService: BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory ?? throw new ArgumentNullException(nameof(scopeFactory));
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
// ...
using (var scope = _scopeFactory.CreateScope())
{
var myScopedService = scope.ServiceProvider.GetRequiredService<IScopedService>();
myScopedService.DoWork();
}
// ....
}
}
您可以在此處找到更多詳細資訊
uj5u.com熱心網友回復:
我不明白的是我認為你可以從單身人士中消費一個范圍?
然后這里是解釋:你想錯了。你的想法其實毫無意義。
- DataAccess 是一個單例。永遠只有一個。
- 背景關系被插入到建構式中。
由于背景關系可以有多個 - 這意味著第一個將被插入到資料訪問中。你永遠無法使用另一個。
一般來說 - 除了作為存盤庫的 DataAccess 是一個史詩般的反模式 - 注入 db 背景關系是沒有意義的,除非你只有一個 DataAcess 實體,然后你也可以或應該有一個單例背景關系。
這種想法實際上毫無意義。現在,我會擺脫 DataAccess(或解雇你),但除此之外,你有兩種方法來處理這個問題:
- 接受您只有一個資料訪問權限,向其中注入一個單例 dbcontext。
- 如果需要范圍,請將兩者都設定為范圍。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/361540.html
