我已经实现了一个对数据库执行多项操作的代码。现在我决定将其并行化以提高性能。为此,我已将所有异步操作更改为同步,这给我带来了问题。
代码封装的与事务相关的所有内容,当它变得同步时,不允许使用令牌来定义事务的超时。
以前,如果没有并行化,您可以向 context.database.BeginTransactionAsync 等传递 CancellationTokenSource,这将导致在超出指定时间时生成异常。
现在,在不使用异步操作的情况下,context.database.BeginTransaction 等不允许将 CancellationTokenSource 作为参数传递,因此我失去了事务超时功能。您知道我如何恢复此功能吗?我读过有关使用计时器或任务的内容,但这两个选项都没有说服我。你还有其他想法吗?
您可以查看下面我的代码摘要,以更好地了解我告诉您的内容。
Parallel.ForEach(excelRawList.SuccessRows, options, (excelRow) =>
{
using (var dbContext = new MyContext(new DbContextOptionsBuilder<MyContext>().UseSqlServer(_configuration.GetConnectionString
("connectionstring")).Options))
{
using (var unitOfWork = new UnitOfWork(dbContext))
{
unitOfWork.BeginTransaction();
try
{
int? decision = CanBeInserted(unitOfWork, excelRow.id);
if (decision != 0)
{
if (!excelRow.Store)
{
try
{
if (decision != null)
{
service3.MoveToBackup(unitOfWork, decision.Value);
}
Entity2 entity2ToBeInserted = service1.changeExcelRowToEntity2(excelRow);
excelRow.Entity2 = entity2ToBeInserted;
unitOfWork.Context.Set<Entity2>().Add(entity2ToBeInserted);
unitOfWork.Context.Set<Entity1>().Add(excelRow);
unitOfWork.SaveChanges();
unitOfWork.CommitTransaction();
}
catch (OperationCanceledException ex)
{
unitOfWork.Rollback();
excelRawList.ErrorRows.Add(new ExcelError() {"Timeout ended"});
}
catch (Exception ex)
{
unitOfWork.Rollback();
excelRawList.ErrorRows.Add(new ExcelError() {"Exception"});
}
}
else
{
excelRow.FK_Entity1_Entity2 = null;
unitOfWork.Context.Set<Entity1>().Add(excelRow);
unitOfWork.SaveChanges();
unitOfWork.CommitTransaction();
}
}
else
{
excelRawList.ErrorRows.Add(new ExcelError() {"Repeated"});
}
}
catch (Exception ex)
{
excelRawList.ErrorRows.Add(new ExcelError() {"Exception"});
}
}
}
});
Parallel.ForEachAsync
即可使用异步函数体。沿着这些思路:
CancellationToken = ...;
Parallel.ForEachAsync(
new[] { new object() },
new ParallelOptions(),
async (excelRow, ct) =>
{
// ...
// ct is linked with the someCt passed to the Parallel.ForEachAsync
await using var tran = await dbContext.Database.BeginTransactionAsync(ct);
// ...
},
someCt);