我应该如何将DbContext
实例注入(使用标准依赖注入)IHostedService
?
我目前让我的IHostedService
类在构造函数中获取MainContext
(从DbContext
派生)实例。
当我运行应用程序时,我得到:
无法使用作用域服务' Microsoft.EntityFrameworkCore.DbContextOptions'来自singleton' Microsoft.Extensions.Hosting.IHostedService'。
所以我尝试通过指定:{/ p>来使DbContextOptions
瞬态
services.AddDbContext<MainContext>(options =>
options.UseSqlite("Data Source=development.db"), ServiceLifetime.Transient);
在我的Startup
课程中。
但错误仍然相同,即使根据this solved Github issue传递的DbContextOptions
应该具有AddDbContext
调用中指定的相同生命周期。
我不能使数据库上下文成为单例,否则对它的并发调用会产生并发异常(由于数据库上下文不能保证是线程安全的。)
答案 0 :(得分:48)
在托管服务中使用服务的一种好方法是在需要时创建范围。这允许使用服务/ db上下文等,并使用它们设置的生存期配置。理论上,不创建范围可能导致创建单例DbContexts和不正确的上下文重用(EF Core 2.0与DbContext池)。
要执行此操作,请注入IServiceScopeFactory
并在需要时使用它来创建范围。然后解决此范围内所需的所有依赖项。如果您希望将逻辑移出托管服务并仅使用托管服务触发某些工作(例如,定期触发任务 - 这将定期创建范围,创建任务服务),这也允许您将自定义服务注册为范围依赖项这个范围也会得到一个db上下文注入)。
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>();
…
}
}
…
}
答案 1 :(得分:2)
您可以在构造函数中添加 create Scope,如下所示:
public ServiceBusQueueListner(ILogger<ServiceBusQueueListner> logger, IServiceProvider serviceProvider, IConfiguration configuration)
{
_logger = logger;
_reportProcessor = serviceProvider.CreateScope().ServiceProvider.GetRequiredService<IReportProcessor>();
_configuration = configuration;
}
添加
using Microsoft.Extensions.DependencyInjection;