【问题标题】:Ignore SqlTransaction.Commit within TransactionScope忽略 TransactionScope 中的 SqlTransaction.Commit
【发布时间】:2012-07-10 17:03:16
【问题描述】:

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

因此我们想到将“旧”和“新”代码包装在 TransactionScope 中。但是,即使 TransactionScope 未完成,周围的 TransactionScope 内的 Commit 也会始终执行。这段代码 sn-p 说明了我的问题:

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 不是一个选项。我们有一个遗留框架,它提交自己的SqlTransactions,并且没有 api 来挂钩其事务机制。

【问题讨论】:

  • 您至少可以访问连接吗?
  • @LadislavMrnka 不,除了配置文件中的连接字符串。

标签: c# entity-framework transactions transactionscope


【解决方案1】:

当 scope.Complete() 没有被命中时,更新语句仍然被提交。

哦不!未使用 TransacationScope1.

自动登记在连接打开(或内部)TransactionScope 时有效。

Open inside TransactionScope 应该解决这个问题(即使是手动事务?)因为 Connection 将 [通常] 自动登记在环境 TS 上下文中。

可以将现有连接加入环境事务范围:connection.EnlistTransaction(Transaction.Current)

另外,TS 可以从现有事务创建,例如new TransactionScope(transaction),在这里可能有用也可能没用。

如果完全没问题,创建手动事务,但 TS(在找出问题后!)使事务处理更简单、更容易.. 至少在大多数情况下 :)

编码愉快!


1 TS 未用于“更新语句”。它仍将 [可能] 用于 context.SaveChanges(),因为这将打开一个 new 连接,然后自动登记。

我在上面提供了一些选项,尽管我不确定普通的“嵌套”事务。查看上下文中使用的(密封的?)API 可能会揭示有关限制/限制的更多见解。

【讨论】:

  • 你是对的!当我将Open 放在 TS 之后时,TS 处于领先地位。而且我认为实际上这也应该发生,因为连接是在旧框架内打开的。但它仍然提交。我将不得不更深入地研究那里发生的事情,看看你的建议是否可以解决这个问题。谢谢,我会回来的。
  • 这让我走上了正轨。我发现旧框架使连接打开的时间比应有的时间长。因此,如果不更改旧代码,就不可能按照我想要的方式使用 TransactionScope - 我们非常不愿意这样做。恐怕我们必须这样做。
猜你喜欢
  • 2013-08-17
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-12
相关资源
最近更新 更多