.NET InvalidOperationException: Cannot consume scoped service from singleton
在.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]'.)”
主要原因是,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();
}
这样就不会报错了。
更新于:5个月前相关文章
- .NET C# EntityFramework(EF)连接SQLite代码示例
- Sylvan.Data.Excel 性能优异的开源.NET Excel数据读取库
- ASP.NET Core 中常用的内置中间件
- .NET9 F#有什么新特性?
- .NET 开源 ORM FreeSql 使用教程
- .NET9 C# 13 有哪些新特性?
- .NET9 开始删除内置的 Swagger 支持 可使用Scalar.AspNetCore替代
- .NET 9 中System.Text.Json 的新增功能
- 什么是.NET渐进式Web应用(PWA)
- .NET开发中常见的异常报错原因和解决方法?
- .NET框架和CLR的工作原理?
- ASP.NET MVC与Web Forms的区别
- .NET C#中的IEnumerable和IEnumerator的区别
- 使用ADO.NET连接到南大通用GBase 8s数据库
- 鸿蒙OpenHarmony系统可以运行跨平台的.NET Core吗?
- ASP.NET Core使用partial标签报错
- .NET 9 即将推出的功能Task.WhenEach
- .NET 使用HttpClientFactory+Polly替代直接使用HttpClient
- .NET Framework被淘汰了吗?
- 强大的 .NET Mock 框架 单元测试模拟库Moq使用教程