返回

.NET InvalidOperationException: Cannot consume scoped service from singleton

2024-05-20 .NET InvalidOperationException scoped singleton 260 0

在.NET windows服务里注入DBContext时会报错:.NET InvalidOperationException: Cannot consume scoped service from singleton。

报错的代码如下:

builder.Services.AddDbContext<ToolsContext>(options => {
    options.UseSqlServer(builder.Configuration.GetConnectionString("Tools"));
});

System.AggregateException:“Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType: Microsoft.EntityFrameworkCore.IDbContextFactory`1[Models.Tools.ToolsContext] Lifetime: Singleton ImplementationType: Microsoft.EntityFrameworkCore.Internal.DbContextFactory`1[Models.Tools.ToolsContext]': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Models.Tools.ToolsContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Models.Tools.ToolsContext]'.) (Error while validating the service descriptor 'ServiceType: Microsoft.Extensions.Hosting.IHostedService Lifetime: Singleton ImplementationType: MyTools.Service.Worker': Cannot consume scoped service 'Microsoft.EntityFrameworkCore.DbContextOptions`1[Models.Tools.ToolsContext]' from singleton 'Microsoft.EntityFrameworkCore.IDbContextFactory`1[Models.Tools.ToolsContext]'.)”

.NET InvalidOperationException: Cannot consume scoped service from singleton

主要原因是,IHostedService实例中可以注入的对象有限制。我们可以注入的两种依赖注入生命周期是Singleton 和 _Transient_。这使得我们不能像ASP.NET Core那样直接将一个DbContext注入,因为AddDbContext<TContext>()方法会将我们的上下文注册为Scoped服务。

解决方法是使用IDbContextFactory将DbContext实例注入到IHostedService,这将把一个IDbContextFactory<TContext>实例作为一个Singleton服务添加到DI容器中,代码如下:

builder.Services.AddDbContextFactory<ToolsContext>(options => {
    options.UseSqlServer(builder.Configuration.GetConnectionString("Tools"));
});

在需要使用DBContext的地方,我们在注入的IDbContextFactory<ToolsContext>上调用CreateDbContextAsync()方法。这将初始化我们的DbContext类,然后我们可以用它来操作数据库了。代码如下:

IDbContextFactory<ToolsContext> _contextFactory;

public Worker(IDbContextFactory<ToolsContext> contextFactory)
{
    _contextFactory = contextFactory;
}

// 获取DBContext对象
using (var _toolContext = await _contextFactory.CreateDbContextAsync(stoppingToken)) {
    var webSites = await _toolContext.WebSites.ToListAsync();
}

这样就不会报错了。

您可能感兴趣:

阿里云 云服务器 99元1年 2核2G 3M固定带宽 续费与新购同价

DOVE 网络加速器免费试用

顶部