【问题标题】:does transactionscope get properly disposed?交易范围是否得到妥善处置?
【发布时间】:2017-05-12 18:18:03
【问题描述】:

我在我们的代码库中发现了一个可能的问题,即开发人员忘记用花括号括住 using 语句的内容:

        using (TransactionScope transactionScope = new TransactionScope(Transaction.Current))
            try
            {
                RecordUserConnectionCore(context, userName);
                transactionScope.Complete();
            }
            catch
            {
                transactionScope.Dispose();
                throw;
            }

try/catch 是否在 using 语句中执行? transactionScope 是否正确处置?

请注意,这个问题是关于 try/catch 块是否在 using 上下文中执行的。我问是因为 try/catch 代码周围没有大括号。

【问题讨论】:

  • 您不需要在事务中使用 try-catch 来管理事务的完整性。
  • 我的问题是关于花括号的使用,而不是关于使用 /idisposable 的工作原理
  • 是否应该有大括号来清楚地传达打算成为 using 块的一部分的内容? IMO,是的,当然。在这种情况下,try/catch 是 using 块的一部分吗?是的。而 catch 中的 Dispose() 调用是多余的。这意味着整个 try/catch 块完全没有意义,因为它所做的一切(除了不必要的 Dispose() 调用)就是重新抛出异常。
  • 当没有大括号时,只有下一条语句将是代码块的主体。在这种情况下,主体是 TRY/CATCH。但在你的例子中,你真的不需要所有的开销。您正在使用 try/catch 来管理事务范围,然后只是重新抛出原始错误。您不妨删除 try catch 并将两个语句作为正文放在 USING 中。

标签: c# sql .net sql-server visual-studio


【解决方案1】:

重新阅读后,我意识到我错过了实际问题。

是的,try/catchusing 块“内”,即使using 语句没有大括号。

如果一个块没有大括号,则该块隐含地只包含下一个语句或块

所以用另一个例子,你可以这样做:

if(x = 1)
{
    try{}
    catch{}
}

或者这个

if(x=1)
try{}
catch{}

两者完全相同。

为了可读性,我通常会添加大括号。我觉得还是比较清楚一点,不知道语法细节的人也不会迷惑。


是的,在您的代码中,TransactionScope 总是被处理掉。

通过将其放入using 块中调用Dispose,如果出现异常,Dispose 会被调用两次。它在catch 块中调用一次,并在using 块的末尾再次调用。 (这不会抛出异常,但它是不必要的。)

using 块意味着 transactionScope 已经被释放,即使有异常。所以你可以这样做:

using (TransactionScope transactionScope = new TransactionScope(Transaction.Current))
{
    RecordUserConnectionCore(context, userName);
    transactionScope.Complete();
}

【讨论】:

    【解决方案2】:

    Try/Catch 在 using 块内执行。您的代码与您的代码完全相同:

    using (TransactionScope transactionScope = new TransactionScope(Transaction.Current))
    {
          try
          {
               RecordUserConnectionCore(context, userName);
               transactionScope.Complete();
          }
          catch
          {
              transactionScope.Dispose();
              throw;
          }
    }
    

    你可以知道这是真的原因之一是因为

    transactionScope.Dispose(); 
    

    行编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-24
      • 1970-01-01
      • 2019-04-26
      相关资源
      最近更新 更多