wake-up-neo.com

Wie soll ich eine DbContext-Instanz in einen IHostedService einfügen?

Frage

Wie soll ich eine DbContext -Instanz in eine IHostedService-Instanz injizieren (mit der Standard-Abhängigkeitsinjektion)?

Was habe ich versucht

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).

28
Shoe

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>();
            …
        }
    }
    …
}
63
Martin Ullrich