我正在使用实体框架,我有几种使用事务的方法。我收到此错误:连接已在事务中,无法参与另一个事务。 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;
}
答案 0 :(得分: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;
}
但是,你这样做是一种反模式。打开交易时未进行的每次“保存更改”都是一次交易。
您应该做的是在您的业务逻辑中开始您的事务,并在同一级别提交它。
// 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();
}
答案 1 :(得分:0)
让我为您提供一个已经回答的问题的替代方法。
您可以检查是否已创建交易,并改为使用它。
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);
,它将创建一个新交易并使用它