我应该如何注入(使用.NET Core的内置依赖注入库MS.DI)一个DbContext
示例到Singleton中?在我的特定情况下,单例是IHostedService
?
我尝试了什么
我目前让我的IHostedService
类在构造函数中接受一个MainContext
(派生自DbContext
)示例。
当我运行应用程序时,我得到:
无法从单例“Microsoft.Extensions.Hosting. IHostedService”使用作用域服务“Microsoft.EntityFrameworkCore.DbContextOptions”。
因此,我尝试通过指定使DbContextOptions
成为 transient :
services.AddDbContext<MainContext>(options =>
options.UseSqlite("Data Source=development.db"),
ServiceLifetime.Transient);
在我的Startup
类中。
但是错误仍然是相同的,即使根据this solved Github issue,传递的DbContextOptions
应该具有与AddDbContext
调用中指定的相同的生存期。
我不能使数据库上下文成为单例,否则对它的并发调用将产生并发异常(由于数据库上下文不能保证是线程安全的)。
3条答案
按热度按时间qgzx9mmu1#
在托管服务中使用服务的一个好方法是在需要时创建一个范围。这允许使用服务/数据库上下文等。使用它们设置的生存期配置。不创建作用域在理论上可能会导致创建单例DbContext和不正确的上下文重用(EF Core 2.0 with DbContext pools)。
为此,注入一个
IServiceScopeFactory
,并在需要时使用它创建一个作用域。然后从这个范围中解决您需要的任何依赖项。这还允许您将自定义服务注册为范围依赖项,如果您希望将逻辑移出托管服务并仅使用托管服务来触发某些工作(例如定期触发任务-这将定期创建范围,在该范围中创建任务服务,该任务服务还获得注入的数据库上下文)。72qzrwbm2#
可以在构造函数中添加create Scope,如下所示:
做加法
dw1jzc5e3#
针对单例服务消费
DbContext
的具体情况自.NET 5起,您可以为
DbContext
注册IDbContextFactory<TContext>
并将其注入到单例服务。使用
AddDbContextFactory<TContext>
注册工厂:AddDbContextFactory()
时删除AddDbContext()
,因为后者也将上下文类型本身注册为作用域服务。在singleton服务中,注入
IDbContextFactory<TContext>
并使用CreateDbContext()
在需要的地方创建DbContext
的示例:参见
MS Docs:使用DbContext工厂(例如Blazor)
备注
不要混淆:
IDbContextFactory<TContext>
来自 Entity Framework(4.3.1,5.0.0,6.2.0)。IDbContextFactory<TContext>
来自 Entity Framework Core(1.0,1.1,2.0,2.1,2.2)。