执行策略“SqlServerRetryingExecutionStrategy”不支持用户启动的事务

Ser*_*rge 14 c# telerik entity-framework-core asp.net-core asp.net-core-5.0

我有一个 ASP.NET Core 5 MVC Web 应用程序,使用 Entity Framework Core 5。

我们实现 Web 组件,例如网格或电子表格(我们与 Telerik 合作)。当我在组件中进行一些更改,然后尝试保存更改时,组件会调用 my ApplicationDbContext.SaveChanges. 然后我收到以下错误:

System.InvalidOperationException:配置的执行策略“SqlServerRetryingExecutionStrategy”不支持用户启动的事务。使用“DbContext.Database.CreateExecutionStrategy()”返回的执行策略将事务中的所有操作作为可重试单元执行。

在此输入图像描述

这是我ConfigureServices用于 DBContext 的方法:

public static void AddDbContext(this IServiceCollection services, string connectionString) =>
    services.AddDbContext<ApplicationDbContext>(options =>
    {
        options.UseSqlServer(connectionString,
            providerOptions =>
            {
                providerOptions
                    .EnableRetryOnFailure(
                        maxRetryCount: 5, 
                        maxRetryDelay: TimeSpan.FromSeconds(30),
                        errorNumbersToAdd: null)
                    .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery);
            });
        options.EnableSensitiveDataLogging();
        options.ConfigureWarnings(w => w.Throw(RelationalEventId.MultipleCollectionIncludeWarning));
    });
Run Code Online (Sandbox Code Playgroud)

该错误不会系统地发生。当然,当我尝试将多个元素保存到数据库时。而且当只有一个元素时也是如此。当我以经典形式逐一编辑或相同元素时不会发生,只有当它发生在多个对象场景(网格或电子表格)中时...

StackTrace 会是这样的: 在此输入图像描述

作为示例,我给出了一个方法,允许将Entreprise对象从电子表格提交到数据库,以便使用CreateExecutionStrategy方法:

public ActionResult Data_Source_Entreprises_Submit(SpreadsheetSubmitViewModel model)
{
    var result = new SpreadsheetSubmitViewModel()
    {
        Created = new List<SpreadsheetEntrepriseViewModel>(),
        Updated = new List<SpreadsheetEntrepriseViewModel>(),
        Destroyed = new List<SpreadsheetEntrepriseViewModel>()
    };

    if ((model.Created != null || model.Updated != null || model.Destroyed != null) && ModelState.IsValid)
    {
        /*             executionStrategy                                 */
        var executionStrategy = _dbContext.Database.CreateExecutionStrategy();

        executionStrategy.Execute(() =>
            {
                using (var transaction = _dbContext.Database.BeginTransaction())
                {
                    try
                    {
                        ///////// Business Logic //////////////////
                        if (model.Created != null)
                        {
                            foreach (var created in model.Created)
                            {
                                EntrepriseDTO dto = new EntrepriseDTO() { Nom = created.Nom };
                                var createdDto = _entrepriseService.Create(dto);
                                created.Id = createdDto.Id;
                                result.Created.Add(created);
                            }
                        }

                        if (model.Updated != null)
                        {
                            foreach (var updated in model.Updated)
                            {
                                var spec = new EntrepriseForDetailsSpecification(updated.Id);
                                var dto = _entrepriseService.Read(spec);
                                dto.Nom = updated.Nom;
                                _entrepriseService.Update(dto);
                                result.Updated.Add(updated);
                            }
                        }

                        if (model.Destroyed != null)
                        {
                            foreach (var destroyed in model.Destroyed)
                            {
                                _entrepriseService.Delete(destroyed.Id);
                                result.Destroyed.Add(destroyed);
                            }
                        }
                        ///////// END Business Logic ///////////////

                        transaction.Commit();
                    }
                    catch (Exception ex)
                    {
                        transaction.Rollback();
                    }
                }
            }
        );
        /*             END executionStrategy                   */
        
        return Json(result);
    }
    else
    {
        return StatusCode(400, "The models contain invalid property values.");
    }
}
Run Code Online (Sandbox Code Playgroud)

结果我遇到了以下错误:

连接不支持 MultipleActiveResultSets

然后我修改了连接字符串,包括MultipleActiveResultSets=True,但最后又得到了另一个错误:

在前一个操作完成之前,在此上下文中启动了第二个操作。这通常是由不同线程同时使用同一个 DbContext 实例引起的。有关如何避免 DbContext 的线程问题的详细信息,请参阅 https://go.microsoft.com/fwlink/?linkid=2097913

我没有在该代码中使用异步代码,我不知道出了什么问题......

Ser*_*rge 14

我需要验证我的所有存储库异步调用,并查看是否所有调用都已“等待”。

我发现一个没有“等待”的...修复允许我将对象从数据库中的网格(或电子表格)保存。更多信息请参阅有关EF Core 异步编程的 MS 文档...