// here, sometimes getting old data or actual data but conflict updates, on multiple calls at the same time
var readyProduct = await _readyProductRepository.FindAsync(p => p.ModelId == readyProductCreate.ModelId);
if (readyProduct == null)
{
readyProduct = _mapper.Map<ReadyProductCreate, ReadyProduct>(readyProductCreate);
await _readyProductRepository.AddAsync(readyProduct);
}
else
{
readyProduct.Count += readyProductCreate.Count;
_readyProductRepository.Update(readyProduct);
}
var transaction = new ReadyProductTransaction
{
ModelId = readyProductCreate.ModelId,
Count = readyProductCreate.Count,
Status = ReadyProductTransactionType.Import,
Date = DateTime.Now,
};
await _transactionRepository.AddAsync(transaction);
await _unitOfWork.SaveAsync();
我用隔离级别
Transaction
覆盖了Serializable
中的整个过程,但它造成了deadlock
。
可能,在插入
trigger
表后创建一个 ReadyProductTransaction
来更新 ReadyProduct
表将是一个解决方案,但我想知道是否可以在没有触发器的情况下实现。
DbContext - 注册为作用域
所有存储库类,包括 UnitOfWork 类 - 注册为 Scoped
应用程序-.NET5.0
应用程序运行于 - IIS
Serializable
事务更有可能(而非更少)导致死锁,因为它们锁定的次数更多、时间更长。
这并不意味着您不应该使用它们:更好的隔离总是更有利于数据完整性。您只需要正确使用它们即可。
始终确保以相同的顺序锁定表,并尝试确保在此类锁中使用相同的索引。使用更新锁。这可以通过限制对独占锁的访问来防止死锁,同时仍然允许运行纯读查询。
SELECT FOR UPDATE
UPDLOCK
var readyProduct = await _dbContext
.FromSqlRaw<ReadyProduct>("SELECT * FROM dbo.ReadyProduct WITH (UPDLOCK)")
.Where(p => p.ModelId == readyProductCreate.ModelId)
.FirstOrDefaultAsync();