一尘不染

如何将DbContext实例注入IHostedService?

c#

我应该如何将DbContext实例注入(使用标准依赖注入)IHostedService

我尝试了什么

目前,我的IHostedService类在构造函数中采用了MainContext(源自DbContext)实例。

当我运行该应用程序时,我得到:

无法使用单例“ Microsoft.Extensions.Hosting.IHostedService”中的作用域服务“
Microsoft.EntityFrameworkCore.DbContextOptions”。

因此,我尝试DbContextOptions通过指定以下方式进行过渡:

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

在我Startup班上。

但是,错误仍然保持不变,即使根据此已解决的Github问题,所DbContextOptions传递的应该具有与AddDbContext调用中指定的生存期相同的生存期。

我不能使数据库上下文成为单例,否则对其的并发调用将产生并发异常(由于不能保证数据库上下文是线程安全的)。


阅读 1310

收藏
2020-05-19

共1个答案

一尘不染

在托管服务中使用服务的一种好方法是在需要时创建作用域。这允许将服务/数据库上下文等与设置它们的生命周期配置一起使用。从理论上说,不创建范围可能导致创建单例DbContext和不正确的上下文重用(带有DbContext池的EF
Core 2.0)。

为此,请插入,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>();
            …
        }
    }
    …
}
2020-05-19