忽略TransactionScope中的SqlTransaction.Commit

Ger*_*old 6 c# entity-framework transactions transactionscope

我们正在逐步用实体框架(4.3.1)替换遗留数据访问代码.在某些情况下,我们无法避免在一个工作单元中使用两种数据访问方式.理想情况下,这应该在一个事务中完成.但是,旧代码使用在完成工作单元时SqlTransaction调用的s,Commit()并且EF管理自己的事务.

所以我们考虑将"旧"和"新"代码包装在一个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(); 
  }
}
Run Code Online (Sandbox Code Playgroud)

未命中时仍会提交更新语句scope.Complete().

所以看起来,我不能TransactionScope用来强制旧数据访问代码和SaveChanges上下文在一个事务中执行.或者有没有办法推翻SqlTransaction.Commit语句?

我知道这里有关于TransactionScope和SqlTransaction的更多帖子,但他们都(正确地)说使用TransactionScope时不需要(也不推荐)使用SqlTransaction.但不使用SqlTransaction不是一个选项.我们有一个遗留框架,它提交自己的SqlTransactions并且没有api可以挂钩它的事务机制.

小智 8

当未触发scope.Complete()时,仍会提交更新语句.

不好了!!TransacationScope未被使用1.

当在TransactionScope 之后(或内部)打开Connection时,自动登记有效.

Open 里面TransactionScope 应该解决这个问题(甚至与手动交易?)作为连接然后将[通常]在环境TS上下文自动征用.

可以将现有连接登记到环境事务范围中:connection.EnlistTransaction(Transaction.Current).

或者,可以从现有交易创建TS,例如new TransactionScope(transaction),这在这里可能有用或者可能没有帮助.

创建一个手动交易,如果完全没问题,但TS(在解决问题之后!)使处理交易更简单,更容易..至少在大多数情况下:)

快乐的编码!


1 TS未用于"更新声明".它仍然[可能]用于context.SaveChanges()打开一个新的连接,然后自动登记.

我上面提供了一些选项,虽然我不确定简单的"嵌套"事务.看到上下文中使用的(密封?)API可能会揭示有关限制/限制的更多见解.