Как я должен ввести экземпляр DbContext в IHostedService?

вопрос

как я должен впрыснуть (используя стандартную инъекцию зависимостей) a DbContext экземпляр в IHostedService?

что я пробовал

у меня в настоящее время есть мой IHostedService класс take a MainContext (извлечение из DbContext) экземпляр в конструкторе.

когда я запускаю приложение, я получаю:

не удается использовать службу с областью " Microsoft.EntityFrameworkCore.DbContextOptions ' из singleton 'Майкрософт.Увеличение.Размещающий.IHostedService'.

поэтому я попытался сделать DbContextOptions переходный, указав:

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

в своем Startup класса.

но ошибка остается той же, хотя, по данным это решило проблему Github на DbContextOptions прошло должны иметь тот же срок службы, указанный в элементе AddDbContext звонок.

я не могу сделать контекст базы данных одноэлементным, иначе параллельные вызовы к нему дадут параллелизм исключения (из-за того, что контекст базы данных не гарантируется потокобезопасность).

1 ответов


хорошим способом использования служб внутри размещенных служб является создание области при необходимости. Это позволяет использовать контексты служб / БД и т. д. с конфигурацией жизни они устанавливаются. Не создание области теоретически может привести к созданию одноэлементных DbContexts и неправильному повторному использованию контекста (EF Core 2.0 с пулами DbContext).

чтобы сделать это, введите IServiceScopeFactory и используйте его для создания области, когда это необходимо. Затем разрешите все зависимости, которые вам нужны из этой области. Это также позволяет регистрировать пользовательские службы как зависимости области, если вы хотите переместить логику из размещенной службы и использовать размещенную службу только для запуска некоторой работы (например, регулярно запускать задачу - это будет регулярно создавать области, создавать службу задач в этой области, которая также получает контекст БД).

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