c# - net - Como devo injetar uma instância DbContext em um IHostedService?



hosted service net core (1)

Uma boa maneira de usar serviços dentro de serviços hospedados é criar um escopo quando necessário. Isso permite usar contextos de serviços / db etc. com a configuração de vida útil com a qual eles estão configurados. Não criar um escopo poderia, em teoria, levar à criação de DbContexts singleton e à reutilização imprópria do contexto (EF Core 2.0 com pools DbContext).

Para fazer isso, injete um IServiceScopeFactory e use-o para criar um escopo quando necessário. Em seguida, resolva todas as dependências necessárias nesse escopo. Isso também permite registrar serviços personalizados como dependências com escopo, caso você queira mover a lógica do serviço hospedado e usar o serviço hospedado apenas para acionar algum trabalho (por exemplo, acionar uma tarefa regularmente - isso criaria escopos regularmente, criaria o serviço de tarefa em este escopo que também recebe um contexto de db injetado).

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

Questão

Como devo injetar (usando a injeção de dependência padrão) uma instância IHostedService em um IHostedService ?

O que eu tentei?

Eu tenho atualmente minha classe IHostedService tomar uma instância de MainContext (derivando de DbContext ) no construtor.

Quando executo o aplicativo, recebo:

Não é possível consumir o serviço com escopo 'Microsoft.EntityFrameworkCore.DbContextOptions' do singleton 'Microsoft.Extensions.Hosting.IHostedService'.

Então eu tentei fazer o transiente DbContextOptions especificando:

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

na minha classe de Startup .

Mas o erro permanece o mesmo, embora, de acordo com esse problema resolvido do Github, o DbContextOptions transmitido tenha o mesmo tempo de vida especificado na chamada AddDbContext .

Não consigo tornar o contexto do banco de dados um singleton, caso contrário, as chamadas simultâneas a ele produziriam exceções de simultaneidade (devido ao fato de que o contexto do banco de dados não tem garantia de ser thread-safe).





.net-core