如何在Entity Framework Core中实现环境事务?

时间:2017-08-28 12:28:07

标签: c# entity-framework transactions

我需要在两个模型下实现事务(使用两个分离的有界上下文)。所以这样的代码:

  using (TransactionScope scope = new TransactionScope())
  {  
       //Operation 1
        using(var context1 = new Context1())
       {
           context1.Add(someCollection1);
           context1.SaveChanges();
       }
       //Operation 2
       using(var context2 = new Context2())
       {
           context2.Add(someCollection2);
           context2.SaveChanges();
       }

       scope.Complete();
   }

返回异常:

  

检测到环境事务。实体框架核心确实如此   不支持环境事务。看到   http://go.microsoft.com/fwlink/?LinkId=800142

在链接中,他们建议在两个上下文中使用一个连接。并使用context2来使用context1的块。

但如果我为每个模型使用自己的控制器/服务:

using (TransactionScope scope = new TransactionScope())
{  
      service1.DoWork();
      service2.DoWork();

       scope.Complete();
 }

我该如何实现?在方法中添加连接作为参数 - 似乎很荒谬。与连接的Init服务也是个坏主意。

3 个答案:

答案 0 :(得分:1)

您可以像这样使用'contexts':

using (var context1 = new Context1())
{
    using (var transaction = context1.Database.BeginTransaction())
    {
        try
        {
            context1.Add(someCollection1);
            context1.SaveChanges();

            // if we don't have errors - next step 
            using(var context2 = new Context2())
            {
               // second step
               context2.Add(someCollection2);
               context2.SaveChanges();
            }   

            // if all success - commit first step (second step was success completed)
            transaction.Commit();
        }
        catch (Exception)
        {
            // if we have error - rollback first step (second step not be able accepted)
            transaction.Rollback();
        }
    }
}

如果您将使用许多控制器/服务,那么您可以使用内部方法将DbConnection传递到您的服务方法中。您必须封装低层逻辑。

使用连接的Init服务也是个坏主意。 - 可能你是对的。但您可以尝试使用一个连接和单个事务初始化两个方法。

见下一个答案,他们可以帮助你:

答案 1 :(得分:0)

在摘要下方使用

using (var context = new MyContext())
{
using (var transaction = context.Database.BeginTransaction())
{
    try
    {
        var customer = context.Customers
            .Where(c => c.CustomerId == 2)
            .FirstOrDefault();
            customer.Address = "43 rue St. Laurent";

        context.SaveChanges();
         
        var newCustomer = new Customer
        {
            FirstName = "Elizabeth",
            LastName = "Lincoln",
            Address = "23 Tsawassen Blvd."
        };
         
        context.Customers.Add(newCustomer);
        context.SaveChanges();

        transaction.Commit();
    }
    catch (Exception)
    {
        transaction.Rollback();
    }
}
}

更多详细信息:https://entityframeworkcore.com/saving-data-transaction

答案 2 :(得分:0)

关于您对How should I implement this?的声明:

using (TransactionScope scope = new TransactionScope())
{  
      service1.DoWork();
      service2.DoWork();

      scope.Complete();
 }

我正在使用控制器 > 服务 > 存储库模式,我发现在使用异步选项时同样的错误已为我解决。每个存储库都按照通常的方法在 Startup.cs 中注入了一个 db 上下文。也许这是在较新版本的 .NET Core 中修复的,或者我只是在存储库中使用相同的上下文实例?以下对我有用:

using (TransactionScope scope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{  
      service1.DoWork();
      service2.DoWork();

      scope.Complete();
 }