我们正在逐步用实体框架 (4.3.1) 替换遗留数据访问代码。在某些情况下,我们无法避免在一个工作单元中同时使用两种数据访问方式。理想情况下,这应该在一个事务中完成。但是,旧代码使用s在完成工作单元并且 EF 管理自己的事务时SqlTransaction
调用。Commit()
所以我们想到将“旧”和“新”代码包装在一个TransactionScope
. TransactionScope
但是,即使TransactionScope
未完成,始终会执行周围环境中的 Commit 。此代码段说明了我的问题:
using (var conn = new SqlConnection("connection string"))
{
conn.Open();
using (var scope = new TransactionScope())
{
using (var tr = conn.BeginTransaction())
{
using (var cmd = conn.CreateCommand())
{
cmd.Transaction = tr;
cmd.CommandText = "some update statement";
cmd.ExecuteNonQuery();
}
tr.Commit();
}
// In reality the code above is part of a legacy DAL, immutable.
// (can't insert SaveChanges before tr.Commit).
context.SaveChanges();
if (<all ok>) // pseudo code for exception handling.
scope.Complete();
}
}
未命中时仍会提交更新语句。scope.Complete()
所以看起来,我不能TransactionScope
用来强制旧的数据访问代码和SaveChanges
来自上下文的 a 在一个事务中执行。或者有没有办法推翻 SqlTransaction.Commit 语句?
我知道这里有更多关于 TransactionScope 和 SqlTransaction 的帖子,但他们都(正确地)说在使用 TransactionScope 时不需要(也不推荐)使用 SqlTransaction。但是这里不使用 SqlTransaction 不是一个选项。我们有一个遗留框架,它提交自己的SqlTransaction
s 并且没有 api 来挂钩其事务机制。