实体框架 6.1.0 保存更改异步
本文关键字:保存更改 异步 框架 实体 | 更新日期: 2023-09-27 17:56:45
我有 EF 帮助程序类,可以异步保存更改:
public async Task<int> SaveOrUpdateAsync<TEntity>(TEntity entity)
where TEntity : class, IContextEntity
{
if (entity.Id == 0)
context.Set<TEntity>().Add(entity);
else
{
TEntity dbEntry = context.Set<TEntity>().Find(entity.Id);
if (dbEntry != null) dbEntry = entity;
}
return await context.SaveChangesAsync();
}
public void Save()
{
Task saveEntit1Async = repository.SaveOrUpdateAsync<Entity1>(entity1);
Task saveEntity2Async = repository.SaveOrUpdateAsync<Entity2>(entity2);
Task saveEntity3Async = repository.SaveOrUpdateAsync<Entity3>(Entity3);
Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async);
string test = "test";
)
通话卡住
Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async);
行,永远无法到达
string test = "test";
但是如果我运行它:
public void Save()
{
repository.SaveOrUpdateAsync<Entity1>(entity1);
repository.SaveOrUpdateAsync<Entity2>(entity2);
repository.SaveOrUpdateAsync<Entity3>(Entity3);
string test = "test";
)
它工作正常,所有更改都被保存,它到达
string test = "test";
为什么
Task.WaitAll(saveEntit1Async, saveEntity2Async, saveEntity3Async);
冻结操作,从不将调用传递到下一行代码(字符串测试 = "test";) ?
我想通了!
这是正在发生的问题,当您使用"等待"方法等待任务或直接从任务的"结果"属性获取结果时,您阻止了主线程与此同时。当任务最终在线程池中的该方法(SaveOrUpdateAsync(TEntity 实体))中完成时,它将调用延续以回发到主线程(因为它从未离开过它),因为 SynchronizationContext.Current 可用并被捕获。但是这里有一个问题:主线程被"等待"方法阻止,这就是我陷入僵局的原因!
为了解决死锁问题,我必须指定不要继续捕获上下文的上下文。SaveChangesAsync().
public async Task<int> SaveOrUpdateAsync<TEntity>(TEntity entity)
where TEntity : class, IContextEntity
{
if (entity.Id == 0)
context.Set<TEntity>().Add(entity);
else
{
TEntity dbEntry = context.Set<TEntity>().Find(entity.Id);
if (dbEntry != null) dbEntry = entity;
}
return await context.SaveChangesAsync().ConfigureAwait(continueOnCapturedContext: false);
}
也许我很愚蠢(!),但为什么你的代码说
if (dbEntry != null) dbEntry = entity;
当然,如果语句应该是
if (dbEntry == null) dbEntry = entity;
我想 C# 空合并运算符也可以替换这两行
TEntity dbEntry = context.Set<TEntity>().Find(entity.Id) ?? entity;