我尝试使用EF6方式使用事务并注意到以下代码
using (db.Database.BeginTransaction())
{
// something
using (db.Database.BeginTransaction())
{
/// something
}
}
在第二个开始事务中抛出异常,告诉我
The connection is already in a transaction and cannot participate in another
transaction. EntityClient does not support parallel transactions.
不是我想要做一个并行事务,无论在一个连接上可能意味着什么。我只想要一个嵌套的。
这确实不支持正在进行的事情吗?
答案 0 :(得分:1)
限制:我假设,当内部事务失败时,外部事务也应该失败。所以你不想回滚并在内部做其他事情。
我刚遇到问题,当覆盖 SaveChanges
时,应用一些数据库更改跟踪器,但不知道,如果我们已经有一个事务。所以这定义了用例。
我创建了一个自定义事务,如果我们还没有一个事务,它只会启动一个事务。任何提交/回滚/处置仅在我们最初没有事务时应用:
public class FallbackTransaction : IDisposable
{
private readonly System.Data.Entity.Database _database;
private DbContextTransaction _fallbackTransaction;
public FallbackTransaction(System.Data.Entity.Database database)
{
_database = database;
}
public void Dispose()
{
_fallbackTransaction?.Dispose();
}
public void Begin()
{
if (_database.CurrentTransaction == null)
{
_fallbackTransaction = _database.BeginTransaction();
}
}
public void Commit()
{
_fallbackTransaction?.Commit();
}
public void Rollback()
{
_fallbackTransaction?.Rollback();
}
}
然后我创建了一个扩展方法:
public static FallbackTransaction BeginFallbackTransaction(this System.Data.Entity.Database database)
{
var transaction = new FallbackTransaction(database);
transaction.Begin();
return transaction;
}
所以我们可以这样做:
using (var transaction = dbContext.Database.BeginFallbackTransaction())
{
// do something
transaction.Commit();
}
这是基于 the answer 的 jbl 的想法
答案 1 :(得分:0)
您可以使用CurrentTransaction
属性。
using (db.Database.BeginTransaction())
{
if(db.Database.CurrentTransaction!=null)
{
/// something
}
else
{
using (db.Database.BeginTransaction())
{
/// the same something
}
}
}
语法相当尴尬。我经常依赖扩展方法将某些东西包装成一个事务
public static void WrapInTransaction(this DbContext db, Action something)
{
if (db.Database.CurrentTransaction != null)
something();
else
using (db.Database.BeginTransaction())
{
something();
}
}
答案 2 :(得分:0)
在EF6之前,提供更大范围事务的推荐方法是使用TransactionScope对象,该对象仍然有效,但似乎已弃用(请参阅here - 页面底部)