繁体   English   中英

实体框架事务错误

[英]entity framework transaction error

我正在使用实体框架,并且有几种使用事务的方法。 我收到这个错误:连接已经在一个事务中,不能参与另一个事务。 EntityClient 不支持并行事务。 我有多种方法取决于“MethodB”,如下面的代码示例:

public void MethodA(){
    using (var tran = Db.Database.BeginTransaction()){  
        MethodB();
        var tableARecord = new TableARecord();
        try
        {
            _context.TableAs.Add(tableARecord)
            Db.SaveChanges();
        }
        catch (Exception excp)
        {
            tran.Rollback();
            throw;
        }
    }
 }

 public void MethodC(){
    using (var tran = Db.Database.BeginTransaction()){  
        MethodB();
        //do something else
    }
 }

 public int MethodB(){
    int ret = 0
    //exception happens when starting the transaction below
    using (var tran = Db.Database.BeginTransaction()){  
        //do something else
    }
    return ret;
 }

在打开一个新的事务之前,你需要提交前一个,所以你不应该在前一个里面打开一个新的事务。

public void MethodA(){
    using (var tran = Db.Database.BeginTransaction()){  
        try
        {
            MethodB();
            var tableARecord = new TableARecord();
            _context.TableAs.Add(tableARecord)
            Db.SaveChanges();
        }
        catch (Exception excp)
        {
            tran.Rollback();
            throw;
        }
    }
 }

 public int MethodB(){
    int ret = 0
    //exception happens when starting the transaction below
    // The transaction is already open, you should not open a new one.

    //do something else
    return ret;
  }

但是,你这样做的方式是一种反模式。 打开事务时未进行的每个“保存更改”都将是单个事务。

您应该做的是在您的业务逻辑中开始您的事务,并在同一级别提交它。

// Business Logic :
var transaction = Db.Database.BeginTransaction())
try {
     _Repository.MethodA();
     _Repository.MethodB();
     transaction.Commit();
}
catch(){
     transaction.Rollback();
}


//Repository :

public void MethodA(){
    var tableARecord = new TableARecord();
    _context.TableAs.Add(tableARecord)
    Db.SaveChanges();
}

public void MethodA(){
    // Just do some other stuff
    Db.SaveChanges();
}

让我为您提供已回答问题的替代方案。

您可以检查是否已创建事务并使用它。

public async Task MethodA()
{
    using(var transaction = await context.BeginTransaction() )
    {
        await MethodB(transaction);

        //...

        transaction.Commit();
    }
}

public async Task MethodB(IDbContextTransaction transaction)
{
    var isOpen = transaction != null;

    try
    {
        if (!isOpen)
        {
            transaction = await context.BeginTransaction();
        }

        //...

        if (!isOpen)
        {
            transaction.Commit();
        }
    }
    finally
    {
        if (!isOpen)
        {
            transaction.Dispose();
        }
    }
}

通过调用MethodA(); 因此调用MethodB(transaction); ,它将使用当前事务

通过调用MethodB(null); ,它将创建一个新事务并使用它代替

如果MethodB有时是独立于MethodAMethodC ,并且需要将其工作包装在事务中(如@Deblaton Jean-Philippe所指出的,如果该方法仅调用一次SaveChanges则不需要事务),它可以检查是否存在事务,如果没有,则创建一个事务,如下所示:

public int MethodB(){
   int ret = 0
   using (var tran = Db.Database.CurrentTransaction ?? Db.Database.BeginTransaction()) 
   {  
       //do something else
   }
   return ret;
} 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM