c# - EF 和 IHostedService 的多个实例
问题描述
我在我的 DI 容器中注册了多个 IHostedService (BackgroundService) 实例。
services.AddHostedService<ResourceMatchingMessageListeningService>();
services.AddHostedService<ResourceMatchingMessageListeningService2>();
services.AddHostedService<ResourceMatchingMessageListeningService3>();
services.AddHostedService<ResourceMatchingMessageListeningService4>();
services.AddHostedService<ResourceMatchingMessageListeningService5>();
每个服务侦听不同的 Azure 服务总线队列。收到消息时,它会通过 EF Core 写入数据库。如果我运行一个服务,它工作正常,只要我运行 2 个或更多,我就会收到错误:
在前一个操作完成之前,在此上下文上开始了第二个操作。这通常是由使用相同 DbContext 实例的不同线程引起的。
我假设出现此错误是因为 EF Core 不是线程安全的,并且托管服务都在不同的线程中运行。
我厌倦了通过将 EF 的服务生命周期设置为瞬态来解决此问题),但我仍然遇到相同的错误。
services.AddDbContext<MyDataContext>(options =>
options.UseSqlServer(connectionString, sqlServerOptions =>
sqlServerOptions.CommandTimeout(120)),
ServiceLifetime.Transient, ServiceLifetime.Transient);
对这里的潜在解决方案有什么建议吗?
解决方案
您需要为每个托管服务创建一个新的服务范围,然后从该范围请求您的 DbContext。
using var scope = services.CreateScope();
var context = scope.ServiceProvider.GetService<MyDataContext>();
您可能希望为您处理的每条消息创建一个服务范围。甚至可能有一个单独的范围服务来处理每条消息的处理。
不幸的是,该实现开始看起来像一个服务定位器反模式。
推荐阅读
- c# - 将带有计数的嵌套 SQL 转换为 linQ
- sql - 您如何根据记录总数计算具有统计意义的样本量?(Postgres)
- javascript - 需要以不同的方式格式化对象数组
- java - 带有可选按钮的密码字段以使用 vaadin 显示密码
- python - 使用 Python(正则表达式)将数据仅放在数据框中的方括号中
- ansible - ansible-playbook 可以从标准输入而不是文件中读取吗?
- c# - 使用标签助手调用控制器,包括来自 asp.net core mvc 中搜索栏的数据
- c++ - 基于概念的模板成员函数重载
- java - 对这个 HashMap 算法面试题感到困惑
- laravel - 如何格式化以下 laravel 集合