我有一个 Blazor Wasm 应用程序,当我调用端点从数据库中获取卷记录列表时,会生成错误:事务(进程 ID 58)在锁资源上与另一个进程发生死锁,并已被选为死锁受害者。重新运行事务。老实说,我从来没有发生过这个错误,所以我不知道它发生的原因。以前,我的 httpget 端点工作正常。我唯一的结论是,它的发生是因为当从实体框架到数据库sql数据进行select查询时,同时我正在用hangfire执行计划任务,而计划任务指向的是volumetric表,即我的端点指向选择查询的端点相同,正是在那一刻,错误一定会发生。
这是我生成错误的代码:
[HttpGet]
public async Task<ActionResult<NIAResponse<ResponsePaged<VolumetricRecord>>>> Get(
[FromQuery] int Page = 1,
[FromQuery] int PageSize = 10,
[FromQuery] string Filters = null,
[FromQuery] string Sorts = null,
[FromQuery] bool AllItems = false,
[FromQuery] string Culture = "en",
[FromQuery] long IdTypeOperation = 1,
[FromQuery] long IdInstallation = 0,
[FromQuery] long IdEquipment = 0,
[FromQuery] long IdProduct = 0,
[FromQuery] long IdMeasure = 0,
[FromQuery] long IdInformationType = 0,
[FromQuery] string? strDateSearch = "",
[FromQuery] string? strDateEndSearch = "")
{
try
{
var DateSearch = new DateTime();
DateSearch = new DateTime(int.Parse(strDateSearch.Split("-")[0]), int.Parse(strDateSearch.Split("-")[1]), int.Parse(strDateSearch.Split("-")[2]));
var DateEndSearch = new DateTime();
DateEndSearch = new DateTime(int.Parse(strDateEndSearch.Split("-")[0]), int.Parse(strDateEndSearch.Split("-")[1]), int.Parse(strDateEndSearch.Split("-")[2]));
var queriable = _context.VolumetricRecords
.Include(x => x.Equipment).ThenInclude(x => x.Product).ThenInclude(x => x.ProductCatalog)
.Include(x => x.Equipment).ThenInclude(x => x.Product).ThenInclude(x => x.SubProductCatalog)
.Include(x => x.Equipment).ThenInclude(x => x.Product).ThenInclude(x => x.UnitOfMeasurementCatalog)
.Include(x => x.Equipment).ThenInclude(x => x.Level).ThenInclude(x => x.Permission)
.Include(x => x.Measure)
.Include(x => x.Hose)
.Include(x=> x.TaxOperation)
.Where(x=>x.Status == true)
.Where(x => x.VolumetricStartDate.Date >= DateSearch.Date && x.VolumetricStartDate.Date <= DateEndSearch.Date)
.OrderBy(x => x.VolumetricStartDate)//RowNumber
.ThenBy(x => x.RowNumber)
.AsQueryable();
queriable = Filter(queriable, Filters, Culture);
queriable = Sort(queriable, Sorts);
ResponsePaged<VolumetricRecord> objResponse = new ResponsePaged<VolumetricRecord>();
var data = await queriable.ToListAsync();
var receipFinales = data;
if (IdInstallation > 0)
{
receipFinales = receipFinales.Where(x => x.Equipment.LevelId == IdInstallation).ToList();
}
if (IdProduct > 0)
{
receipFinales = receipFinales.Where(x => x.Equipment.Product.Id == IdProduct).ToList();
}
if (IdEquipment > 0)
{
receipFinales = receipFinales.Where(x => x.Equipment.Id == IdEquipment).ToList();
}
if (IdMeasure > 0)
{
receipFinales = receipFinales.Where(x => x.IdMeasure == IdMeasure).ToList();
}
if (IdInformationType == (int)TypeOfInformationVolumetric.Todos)
{
if (IdTypeOperation == 1) //Recepcion
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Recepcion_Manual || x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Recepcion)).ToList();
}
else
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Entrega_Manual || x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Entrega)).ToList();
}
}
else if (IdInformationType == (int)TypeOfInformationVolumetric.Automatico)
{
if (IdTypeOperation == 1) //Recepcion
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Recepcion)).ToList();
}
else
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Entrega)).ToList();
}
}
else if (IdInformationType == (int)TypeOfInformationVolumetric.Manual)
{
if (IdTypeOperation == 1) //Recepcion
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Recepcion_Manual)).ToList();
}
else
{
receipFinales = receipFinales.Where(x => (x.TypeOfVolumetricRecord == TypeOfVolumetricRecord.Entrega_Manual)).ToList();
}
}
TypeofEquipment firstEquipmentType = receipFinales.Select(receipt => receipt.Equipment.TypeofEquipment).FirstOrDefault();
if (firstEquipmentType == TypeofEquipment.Dispensario)
{
AcumuladosTotalizadores total = new AcumuladosTotalizadores();
total.Volume = receipFinales.Sum(item => item.VolumenEntregadoTotalizadorInstantaneo) ?? 0.0m;
objResponse.Totes = total;
}
else
{
AcumuladosTotalizadores total = new AcumuladosTotalizadores();
total.Volume = receipFinales.Sum(item => item.VolumetricVolume) ?? 0.0m;
objResponse.Totes = total;
}
objResponse.TotalItemCount = receipFinales.Count();
if (!AllItems)//Cuando solicita todos los datos (se usa para exportar todos los datos a excel)
{
Page = Page <= 0 ? 1 : Page;
if (objResponse.TotalItemCount > PageSize)
receipFinales = receipFinales.Skip(PageSize * (Page - 1)).Take(PageSize).ToList();
}
objResponse.CurrentPageData = receipFinales;
var log = new BasicActionLog
{
IP_Address = getIpMac.GetIp().ToString(),
Mac_Address = getIpMac.GetMac().ToString(),
Action = TypeActionLog.Read.ToString(),
Description = "",
LogType = (int)ELogType.Operaciones_cotidianas,
Component = "Registros volumetricos"
};
await actionLogServices.AddActionLog(log, true);
var logsec = new BasicActionLog
{
IP_Address = getIpMac.GetIp().ToString(),
Mac_Address = getIpMac.GetMac().ToString(),
Action = TypeActionLog.Read.ToString(),
Description = "",
LogType = (int)ELogType.Registro_de_actividad_de_los_usuarios,
Is_Security = true,
Component = "Registros volumetricos"
};
await actionLogServices.AddActionLog(logsec, true);
return new NIAResponse<ResponsePaged<VolumetricRecord>>
{
Code = 200,
Success = true,
Obj = objResponse,
};
}
catch (Exception e)
{
var log = new BasicActionLog
{
IP_Address = getIpMac.GetIp().ToString(),
Mac_Address = getIpMac.GetMac().ToString(),
Action = TypeActionLog.Read.ToString(),
Description = e.Message,
Is_Security = true,
LogType = (int)ELogType.Errores_y_excepciones_en_la_operacion_del_programa,
Component = "Registros volumetricos"
};
await actionLogServices.AddActionLog(log, true);
return new NIAResponse<ResponsePaged<VolumetricRecord>>
{
Code = e.GetHashCode(),
Message = e.Message,
Success = false,
};
}
}
涉及只读事务的死锁最可能的原因是您没有在 SNAPSHOT 隔离中运行或使用 READ COMMITTED SNAPSHOT 数据库选项。您可以在here阅读有关它们的信息,但总结是,通过行版本控制,您不需要 SELECT 查询的任何锁,因此不可能出现死锁。