[英]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
有时是独立于MethodA
和MethodC
,并且需要将其工作包装在事务中(如@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.