【发布时间】:2021-09-25 01:52:29
【问题描述】:
我在我的函数中使用带有 await Task.WhenAll 的异步函数。 有时我收到此消息的异常“在前一个操作完成之前在此上下文上启动了第二个操作。这通常是由不同的线程同时使用相同的 DbContext 实例引起的。有关如何避免 DbContext 线程问题的更多信息”。
public async Task<int> getCountAsync(long userId)
{
return await _appDbContenxt.onTimeRequests
.Where(i => (userId == 0 ? true : i.userId == userId))
.CountAsync()
;
}
public async Task<List<OnTimeRequest>> GetOnTimeRequestsAsync(int pageSize, int currentPage, long userId)
{
return await _appDbContenxt.onTimeRequests
.Where(i => (userId == 0 ? true : i.userId == userId))
.OrderByDescending(i => i.id)
.Skip((currentPage - 1) * pageSize)
.Take(pageSize)
.ToListAsync()
;
}
public async Task<OnTimePaginationDto> getUserOnTimeRequests(int pageSize, int currentPage, long userId)
{
Task<int> count = _onTimeRequestsRepository.getCountAsync(userId);
Task<List<OnTimeRequest>> values = _onTimeRequestsRepository.GetOnTimeRequestsAsync(pageSize, currentPage, userId);
await Task.WhenAll(count, values);
OnTimePaginationDto onTimePaginationDto = new OnTimePaginationDto
{
count = count.Result,
values = _mapper.Map<IList<ReadOnTimeRequestDto>>(values.Result)
};
return onTimePaginationDto;
}
这是我的功能。 getUserOnTimeRequests 在 timeRequestService 中。 timeRequestRepository 中的 getCountAsync 和 GetOnTimeRequestsAsync 。 这是我的启动代码
services.AddScoped<IMemberSheetRepository, MemberShiptRepository>();
services.AddScoped<IPackageHistoryRepository, PackageHistoryRepository>();
services.AddScoped<IOnTimeRequestsRepository, OnTimeRequestsRepository>();
services.AddScoped<IMemberShipService, MemberShipService>();
services.AddScoped<IPackageHistoryService, PackageHistoryService>();
services.AddScoped<IOnTimeRequestService, OnTimeRequestService>();
services.AddDbContext<AppDbContext>(options =>
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking)
.UseSqlServer(Configuration.GetConnectionString("DbConnection")),ServiceLifetime.Transient
);
感谢您的帮助。
【问题讨论】:
-
EF Core 不是线程安全的,你不能那样使用它,你需要在每个并行运行的任务中创建一个新实例
-
@CamiloTerevinto 我该怎么做?
-
@arman Hard。您将无法使用注入的数据库上下文,您需要数据库上下文工厂或类似的东西,以便能够创建数据库上下文、执行查询并在之后进行处理。更简单的是按顺序运行查询,例如
count = await ...; values = await ...;等 -
async != threaded... 这只是意味着操作没有阻塞特定的线程。您的 Task.WhenAll 方法采用不同的线程操作,您需要使用 Task.Run() 调用
标签: asp.net-core entity-framework-core