实体框架交易错误

AAV*_*AAV 2 c# entity-framework transactions

我正在使用实体框架,我有几种方法,我正在使用事务.我收到此错误:连接已在事务中,无法参与另一个事务.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;
 }
Run Code Online (Sandbox Code Playgroud)

Deb*_*ppe 5

在打开新事务之前,您需要提交前一个事务,因此您不应该在上一个事务中打开新事务.

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;
  }
Run Code Online (Sandbox Code Playgroud)

但是,你这样做是一种反模式.打开事务时未进行的每次"保存更改"都是单个事务.

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

// 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();
}
Run Code Online (Sandbox Code Playgroud)


小智 5

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

您可以检查交易是否已创建并使用它。

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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