报错信息:上下文实例在销毁后又被第二次使用
System.InvalidOperationException: A second operation was started on this context instance before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.
相关的代码示例:
resList.ForEach(async item =>
{
var patientInfo = await _patientInfoManager.GetByPatientIndexAsync(item);
});
原因:
DbContext生命周期默认注入是Scope,每一次请求时创建一个实例,在当前请求的上下文中共用,当请求结束后,释放生命周期,释放数据库链接。若开启多线程,在不同的线程中使用同一个DbContext上下文,则报错
相关内容
1. 使用async关键字标识的方法会在一个新的线程中执行。当调用这个方法时,它会在后台启动一个新的任务,并在完成后返回结果。这使得我们可以在调用异步方法的同时继续执行其他任务,而不必等待异步方法完成。
解决方案:
1. forEach 改为正常 for 循环
2. 尝试使用 Parallel.ForEachAsync (为验证)
3. 在构造函数注入IServiceProvider,应用中通过IServiceProvider的GetService方法获取实例
https://www.cnblogs.com/zxsn2014/p/16478922.htmlhttps://www.cnblogs.com/zxsn2014/p/16478922.html
4. 关于3的优化解决方案
2023/8/17
改为ETO通知,继承自ISingletonDependency 单例模式
这种方式感觉可以解决当前的问题
因为我在application层使用了多线程去添加定时任务,使用消息通知将每一个消费者都作为单例模式去消费,就不会出现DbContent上下文销毁的问题。
2023/8/17 个人的解决方案
application层使用 Paella多线程去去处理这个ListA, 每一个线程中不使用仓储方法,而是触发一个Eto出去,在Eto的handle方法内去使用仓储方法。
注意handle要继承自ISingletonDependency,实现单例模式,保证了每个DbContent都是单例,线程之间互相不影响。
2023/8/18 亲测有效的方法
代码中相干的代码段直接开启一个工作单元
使用IUnitOfWorkManager.Begin()方法,如下所示:
public class MyService
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IPersonRepository _personRepository;
private readonly IStatisticsRepository _statisticsRepository;
public MyService(IUnitOfWorkManager unitOfWorkManager, IPersonRepository personRepository, IStatisticsRepository statisticsRepository)
{
_unitOfWorkManager = unitOfWorkManager;
_personRepository = personRepository;
_statisticsRepository = statisticsRepository;
}
public void CreatePerson(CreatePersonInput input)
{
var person = new Person { Name = input.Name, EmailAddress = input.EmailAddress };
using (var unitOfWork = _unitOfWorkManager.Begin())
{
_personRepository.Insert(person);
_statisticsRepository.IncrementPeopleCount();
unitOfWork.Complete();
}
}
}
Reference:
1. https://www.cnblogs.com/zxsn2014/p/16478922.html
2. abpvnext 开发中ValidationErrors和LifetimeScope异常的解决办法_abp vnext 异常处理_吹牛不交税的博客-CSDN博客