在数据库操作中使用超时和并行

问题描述 投票:0回答:1

我已经实现了一个对数据库执行多项操作的代码。现在我决定将其并行化以提高性能。为此,我已将所有异步操作更改为同步,这给我带来了问题。

代码封装的与事务相关的所有内容,当它变得同步时,不允许使用令牌来定义事务的超时。

以前,如果没有并行化,您可以向 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"});
            }
        }
    }
});
c# parallel-processing .net-8.0 parallel-foreach
1个回答
0
投票

您仍然可以这样做 - 只需使用

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);
© www.soinside.com 2019 - 2024. All rights reserved.