gpt4 book ai didi

c# - 多个 DbContext 会产生死锁吗?

转载 作者:行者123 更新时间:2023-11-30 16:09:40 27 4
gpt4 key购买 nike

总结我的代码,我有一个 IRepository<E>使用 DbContextStrategy<E> .

DbContextStrategy<E>DbContext 延伸并使用 DbSet<E>用于数据库上的 LINQ 操作。

E只是泛型传递的实体类型。

在我的 Web API Controller 中,我使用这个存储库接口(interface)来获取我的资源。

但是,一些实体依赖于其他实体。而在 PUTPOST例如请求,我应该验证输入的外键以检查它们是否有效。

因此,我需要实例化一个新的 IRepository<X>其中 X是外部实体类型。

为了让我的开发尽可能简单,我生成了一个基类层,它将为我处理配置、缓存、依赖项注入(inject)和 HTTP 方法绑定(bind)。

在我的最小子 Controller 中,我有以下方法:

/// Base class provides me with the Season entity fetched from the database.
/// An IRepository<Season> is open in the background, and therefore, a DbContext too.
protected override Season UpdateEntity(Season entity, SeasonPostDTO dto)
{
Task<bool> validatingShow = ValidateShow(dto.Show);

entity.Number = dto.Number;
entity.ReleaseDate = dto.ReleaseDate;
entity.Image = dto.Image;
entity.TVShowId = dto.Show;
entity.BlameUserId = Convert.ToInt32(GetCurrentUserId());

validatingShow.Wait();
if (!validatingShow.Result)
throw new EntityNotFoundException("Show not found");

return entity;
}

这是处理实体更新的方法。基础 Controller 会调用它,然后调用 repository.Edit(entity)这将更新 DbContext 中的实体.运行后,IRepository<Season>已处置。

ValidateShow 是一个私有(private)方法,它只检查 showId 是否存在。存在:

private async Task<bool> ValidateShow(int id) {

//This will instantiate a new IRepository<TVShow>, and therefore a new DbContext
return await UseAsyncDependency<TVShow, bool>(async (showRepo) => {

return (await showRepo.ReadAsync(id)) != null;

});
}

然而,ValidateShow方法只是停留在无限循环中。我已经调试了该方法,调用已正确委托(delegate)给 DbSet<TVShow>循环发生在:context.Entities.FindAsync(keys) .

该方法工作正常,因为我使用了相同的 ReadAsync获取 Season 的方法实体。

但是当有两个不同的 DbContext 时,它似乎会产生某种死锁。打开。 (DbSet<Season>DbSet<TVShow>)

我应该注意到 DbContext连接到同一个数据库。

异步/等待从 IRepository 到 DbSet 的执行流程

IRepository<E>调用 SelectAsync(keys) IDao<E> 上的方法,它调用 SelectAsync(keys) DbContextStrategy<E> 上的方法.

这是代码轨迹:

默认存储库:IRepository:

public async Task<E> ReadAsync(params object[] keys) {
if(keys == null || keys.Length < 1) return null;
return await dao.SelectAsync(keys);
}

DefaultDao : IDao

public async Task<E> SelectAsync(params object[] keys) {
return await ForEachStrategyAsync(async (strategy) => {
return await strategy.SelectAsync(keys);
}, (entity) => {
return entity != null;
});
}

private async Task<R> ForEachStrategyAsync<R>(Func<IPersistenceStrategy<E>, Task<R>> function,
Func<R, bool> assertion) {

R lastResult = default(R);
foreach(IPersistenceStrategy<E> strategy in strategies) {
lastResult = await function(strategy);
if(assertion(lastResult)) break;
}
return lastResult;
}

DbContextStrategy : IPersistenceStrategy

public async Task<E> SelectAsync(params object[] keys) {
return await context.Entities.FindAsync(keys);
}

最佳答案

DbContext 的每个实例都有自己的事务,这可能会导致死锁,但您需要一个写操作才能发生,并且 DbContext 仅在您调用 SaveChanges 时将更改保存到数据库() 在调用 validatingShow.Wait()

之前不调用

很有可能是 Wait() 调用出了问题。如果您正在使用 async/await,那么您应该真正对整个调用堆栈使用 async/await(UpdateEntity() 及以上,包括您的 Web API Controller 的方法)

发生这种情况的原因在此处描述 http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html

关于c# - 多个 DbContext 会产生死锁吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27230389/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com