Wie soll ich eine DbContext
-Instanz in eine IHostedService
-Instanz injizieren (mit der Standard-Abhängigkeitsinjektion)?
Ich habe derzeit meine Klasse IHostedService
eine Instanz MainContext
(abgeleitet von DbContext
) im Konstruktor.
Wenn ich die Anwendung starte, erhalte ich:
Der Bereichsdienst "Microsoft.EntityFrameworkCore.DbContextOptions" kann nicht von Singleton "Microsoft.Extensions.Hosting.IHostedService" verwendet werden.
Also habe ich versucht, den DbContextOptions
vorübergehend zu machen, indem ich angab:
services.AddDbContext<MainContext>(options =>
options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);
in meiner Klasse Startup
.
Der Fehler bleibt jedoch derselbe, auch wenn laut dieses gelöste Github-Problem die übergebene DbContextOptions
dieselbe Lebensdauer haben sollte, die im Aufruf von AddDbContext
angegeben wurde.
Ich kann den Datenbankkontext nicht zu einem Singleton machen, da andernfalls bei gleichzeitigen Aufrufen des Datenbankkontexts Ausnahmen von der Parallelität auftreten (aufgrund der Tatsache, dass der Datenbankkontext nicht garantiert threadsicher ist).
Eine gute Möglichkeit, Dienste in gehosteten Diensten zu verwenden, besteht darin, bei Bedarf einen Bereich zu erstellen. Dies ermöglicht die Verwendung von Diensten/Datenbankkontexten usw. mit der Lebensdauerkonfiguration, mit der sie eingerichtet wurden. Wenn theoretisch kein Bereich erstellt wird, kann dies dazu führen, dass Singleton-DbContexts erstellt und der Kontext nicht mehr ordnungsgemäß verwendet wird (EF Core 2.0 mit DbContext-Pools).
Fügen Sie dazu ein IServiceScopeFactory
ein und erstellen Sie damit bei Bedarf einen Bereich. Lösen Sie dann alle Abhängigkeiten, die Sie aus diesem Bereich benötigen. Auf diese Weise können Sie auch benutzerdefinierte Dienste als Abhängigkeiten mit Gültigkeitsbereichen registrieren, wenn Sie die Logik aus dem gehosteten Dienst entfernen und den gehosteten Dienst nur zum Auslösen von Arbeiten verwenden möchten (z. B. regelmäßig eine Aufgabe auslösen - dies würde regelmäßig Gültigkeitsbereiche erstellen und den Aufgabendienst in erstellen dieser Bereich, der auch einen DB-Kontext injiziert bekommt).
public class MyHostedService : IHostedService
{
private readonly IServiceScopeFactory scopeFactory;
public MyHostedService(IServiceScopeFactory scopeFactory)
{
this.scopeFactory = scopeFactory;
}
public void DoWork()
{
using (var scope = scopeFactory.CreateScope())
{
var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();
…
}
}
…
}