执行策略'SqlServerRetryingExecutionStrategy'不支持用户发起的事务。

15
我有一个ASP.NET Core 5 MVC web应用程序,使用Entity Framework Core 5。我们实现了Web组件,如Grid或Spreadsheet(我们使用Telerik)。当我在组件中进行一些更改,然后尝试保存更改时,该组件调用我的。然后我会收到以下错误:System.InvalidOperationException: The configured execution strategy 'SqlServerRetryingExecutionStrategy' does not support user-initiated transactions. Use the execution strategy returned by 'DbContext.Database.CreateExecutionStrategy()' to execute all the operations in the transaction as a retriable unit.

enter image description here

这是我的方法,用于为DBContext配置服务:

在这里,我ConfigureServices

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));
    });

那个错误不是系统性的。当我试图保存多个元素到数据库时,肯定会出现这个错误。但是即使只有一个元素,也会出现这个错误。当我逐个编辑或保存元素时,不会出现这个错误,只有在多个对象的情况下(网格或电子表格)才会出现……

StackTrace如下: enter image description here

例如,我提供了一个方法,允许从电子表格将Enterprise对象提交到数据库,以便使用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.");
    }
}

作为结果,我遇到了以下错误:
连接不支持MultipleActiveResultSets
然后我修改了连接字符串,包括MultipleActiveResultSets=True,但最终获得了另一个错误:
在上一个操作完成之前,在此上下文中启动了第二个操作。这通常是由于不同线程同时使用DbContext实例引起的。有关如何避免与DbContext相关的线程问题的更多信息,请参见https://go.microsoft.com/fwlink/?linkid=2097913
在那段代码中,我没有使用异步代码,我不知道错在哪里...
1个回答

14

我需要验证所有我的存储库异步调用,并检查它们是否全部被"awaited"。

我发现有一个没有被"awaited"的... 修复它使我能够将Grid(或Spreadsheet)中的对象保存到DB中。更多信息在MS文档中关于EF Core异步编程...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接