130 votes

Comment dois-je injecter une instance de DbContext dans un IHostedService?

Question

Comment doit-on injecter (en utilisant la norme de l'injection de dépendances) un DbContext instance en IHostedService?

Qu'ai-je essayé

J'ai actuellement mon IHostedService classe de prendre un MainContext (dérivant de l' DbContext) instance dans le constructeur.

Quand je lance l'application j'obtiens:

Ne peut pas consommer de l'étendue du service 'de Microsoft.EntityFrameworkCore.DbContextOptions " de singleton 'de Microsoft.Extensions.De l'hébergement.IHostedService'.

J'ai donc essayé de l' DbContextOptions transitoire en spécifiant:

services.AddDbContext<MainContext>(options => 
                options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);

dans mon Startup classe.

Mais l'erreur reste la même, même si, selon cette résolu Github problème de la DbContextOptions passé doit avoir la même durée de vie spécifiée dans l' AddDbContext appel.

Je ne peux pas faire le contexte de base de données un singleton autrement appels simultanés à elle donnerait la simultanéité des exceptions (en raison du fait que le contexte de base de données n'est pas garanti d'être thread-safe).

249voto

Martin Ullrich Points 5894

Une bonne façon d'utiliser des services à l'intérieur de services hébergés, est de créer un champ d'application en cas de besoin. Cela permet d'utiliser les services / db contextes etc. avec la durée de vie de configuration, ils sont mis en place avec. Pas la création d'un champ pourrait, en théorie, conduire à la création de singleton DbContexts et une mauvaise contexte de la réutilisation (EF Core 2.0 avec DbContext piscines).

Pour ce faire, injecter IServiceScopeFactory et l'utiliser pour créer un champ d'application en cas de besoin. Résoudre les éventuelles dépendances vous avez besoin de cette étendue. Cela vous permet également d'enregistrer des services personnalisés, comme l'étendue des dépendances si vous souhaitez déplacer la logique du service d'hébergement et d'utiliser le service hébergé uniquement pour déclencher certains travaux (par exemple régulièrement de déclenchement d'une tâche - ce serait de créer régulièrement des portées, de créer le groupe de service dans ce champ d'application, qui reçoit également un db contexte injecté).

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X