在TransactionScope中忽略SqlTransaction.Commit

8
我们正在逐步使用实体框架(4.3.1)替换传统的数据访问代码。在某些情况下,我们无法避免在一个工作单元中同时使用两种数据访问方式。理想情况下,应该在一个事务中完成。然而,旧代码使用了调用Commit()SqlTransaction,而EF则管理其自己的事务。
因此,我们考虑将“旧”和“新”代码包装在TransactionScope中。但是,在包含TransactionScope的情况下,即使TransactionScope未完成,提交仍会被执行。以下代码片段说明了我的问题:
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在一个事务中执行。或者有没有一种方法可以覆盖SqlTransaction.Commit语句?
我知道这里有更多关于TransactionScope和SqlTransaction的帖子,但它们都(正确地)说在使用TransactionScope时不需要(也不建议)使用SqlTransaction。但在这里不使用SqlTransaction是不可选的。我们有一个遗留框架,它提交自己的SqlTransaction,并且没有api可以连接到其事务机制。

你至少有连接的访问权限吗? - Ladislav Mrnka
@LadislavMrnka 不,除了配置文件中的连接字符串以外。 - Gert Arnold
1个回答

9
当未触发scope.Complete()时,更新语句仍然会被提交。
哦不!!没有使用TransactionScope。
只有在连接在事务范围内(或内部)打开后,自动注册才能起作用。
在TransactionScope中放置Open应该可以解决这个问题(即使是手动事务?),因为连接将自动注册到环境TS上下文中。
现有的连接可以注册到环境事务范围中:connection.EnlistTransaction(Transaction.Current)。
或者,TS可以从现有事务创建,例如new TransactionScope(transaction),这对此处可能有所帮助,也可能没有。
手动事务的创建非常好,但是在大多数情况下,在处理事务时使用TS(在弄清楚特殊情况后!)可以使得操作更加简单和容易 :)
祝你编码愉快!
注意:TS并未用于“更新语句”。对于context.SaveChanges(),TS仍然可能被使用,因为它将打开一个新连接,然后自动注册。
我提供了一些选项,尽管我不确定普通的“嵌套”事务。查看上下文中使用的(密封?)API可能会揭示更多关于限制/约束的见解。

你说得对!当我把Open放在TS后面时,TS就会领先。实际上,我认为这也应该发生,因为连接是在旧框架内打开的。但它仍然提交了。我需要深入研究一下那里发生了什么,并看看你的建议是否可以解决这个问题。谢谢,我会回来的。 - Gert Arnold
这让我找到了正确的方向。我发现旧框架比它应该的时间保持连接更长。因此,如果不改变旧代码(我们非常不愿意这样做),就无法按照我想要的方式使用TransactionScope。恐怕我们必须这样做。 - Gert Arnold

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接