使用 System.Transaction 如何更新实体框架中的多行

Posted

技术标签:

【中文标题】使用 System.Transaction 如何更新实体框架中的多行【英文标题】:Using System.Transaction how to update multiple rows in Entity Framework 【发布时间】:2020-04-18 23:11:41 【问题描述】:

我想使用System.Transactions 并更新多行。我的数据库是使用实体框架连接的。

以下是我尝试过的代码,但它会引发错误:

public  void Update(List<PortfolioCompanyLinkModel> record)

    var transaction = _context.Database.BeginTransaction();

    try
    
        foreach (var item in record)
        
            var portfolioCompanyLink = _context.PortfolioCompanyLink.FirstOrDefault(p => p.Id == item.Id);
            portfolioCompanyLink.ModifiedBy = _loggedInUser;
            portfolioCompanyLink.ModifiedOn = DateTime.UtcNow;
            portfolioCompanyLink.URL = item.URL;

            _context.SaveChanges();
            //_context.PortfolioCompanyLink.Update(portfolioCompanyLink);
        

        transaction.Commit();
    
    catch(Exception ex) 
    
        transaction.Rollback();
    

错误:

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

有人可以帮我解决这个问题吗?

【问题讨论】:

【参考方案1】:

你的问题是SqlServerRetryingExecutionStrategy as described in Microsoft documentation

使用重试执行策略时,您可以将多个操作包装在一个事务中。例如,以下代码将两个 SaveChanges 调用包装在一个事务中。如果任一操作的任何部分失败,则不会应用任何更改。

MS docs on resiliency

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

解决方案:手动调用执行策略

var executionStrategy = _context.db.CreateExecutionStrategy();

executionStrategy.Execute(
    () =>
    
        // execute your logic here
        using(var transaction = _context.Database.BeginTransaction()) 
        
            try
            
                foreach (var item in record)
                
                    var portfolioCompanyLink = _context.PortfolioCompanyLink.FirstOrDefault(p => p.Id == item.Id);
                    portfolioCompanyLink.ModifiedBy = _loggedInUser;
                    portfolioCompanyLink.ModifiedOn = DateTime.UtcNow;
                    portfolioCompanyLink.URL = item.URL;
                    _context.SaveChanges();
                    //_context.PortfolioCompanyLink.Update(portfolioCompanyLink);
                

                transaction.Commit();
            
            catch(Exception ex) 
                transaction.Rollback();
            
        
    );

您也可以全局设置策略,但这取决于您要实现的目标。

【讨论】:

我必须为 DefaultSqlExecutionStrategy 使用哪个库? docs.microsoft.com/en-us/dotnet/api/… 是DefaultExecutionStrategy,我错了。 有没有办法使用 system.transactions 进行更新? docs.microsoft.com/en-us/ef/core/saving/transactions 是的,你只需要围绕正确的策略。在答案中你可以看到using(var transaction = _context.Database.BeginTransaction()) 即使我用这个也有必要使用 DefaultExecutionStrategy 吗?

以上是关于使用 System.Transaction 如何更新实体框架中的多行的主要内容,如果未能解决你的问题,请参考以下文章

如何使用更漂亮的特定语言

如何使用 Urllib2 更有效地抓取?

无法在嵌套循环中使用 pandas 附加更大的数据帧。如何更改为 numpy 向量化?

如何在 iOS 上使用气压计获取更准确的海拔数据

如何将代码更改为交换指针而不是使用“临时”指针?

使用 Coffee 进行分类时如何使用更通用的标签