【发布时间】:2021-11-16 17:43:56
【问题描述】:
我有几个“线程”(即 Hangfire 任务)将并行运行这种函数(每个调用传递不同的 systemId):
private void UpdatePartners(int systemId)
{
try
{
using (var ctx = new MyEntities())
{
var partners = ctx.PartnersUpdate.Select(s => s)
.Where(w => w.SystemId.Equals(systemId) && statusToEvaluate.Contains(w.Status)).OrderByDescending(p => p.UpdateAt).Take(500);
var partnersId = partners.Select(p => p.PartnerId).ToList();
var partnersToUpdate = ctx.vPartnersSystems.AsNoTracking().Select(s => s)
.Where(w => w.SystemId.Equals(systemId) && partnersId.Contains(w.Id) && w.Validity.Equals(true))
.ToList();
foreach (var partner in partners)
{
// some operations on "partner", using data from "partnersToUpdate"
ctx.PartnersUpdate.AddOrUpdate(partner);
}
ctx.SaveChanges();
}
}
catch (Exception ex)
{
Logger(ex, "Error on UpdatePartners");
}
}
很遗憾,有时我会收到此错误:
UpdatePartners(Int32 systemId) in C:\myProjects\XYZ\Controllers\TestController.cs:line 16 Void HandleReaderException(System.Exception)
System.Data.SqlClient.SqlException (0x80131904): Transaction (Process ID 130) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
似乎在迭代合作伙伴时(但我可能是错的):
foreach (var partner in partners)
为什么会这样?如果UpdatePartners() 与不同的systemId 并行调用(这意味着查询每次都会捕获不同的记录),为什么它会处理“死锁”?
读取/更新的“相同行”不是死锁吗?
【问题讨论】:
-
首先要尝试的显而易见的事情是将
ToList(Async)添加到产生partners的查询中。这可以防止在执行foreach循环时保持打开状态。作为奖励,它还可以防止您执行两次。
标签: .net entity-framework-6 deadlock .net-4.6.1