I am pondering whether the using TransactionScope should be within a try..catch or the other way around.

Within try..catch

try
{
    using (var scope = new TransactionScope())
    {
        DataBaseStuff();
        scope.Complete();
    }
}
catch (Exception ex)
{
    LogError(ex);
}

Outside:

using (var scope = new TransactionScope())
{
    try
    {
        DataBaseStuff();
        scope.Complete();
    }
    catch (Exception ex)
    {
        LogError(ex);
    }
}

The LLMs are divided, with Gemini, Claude and ChatGPT preferring scope being inside try...catch, while Grok and DeepSeek recommend the opposite.

Is there a "correct" way to implement this?

2 Replies 2

The using statement just ensures that Dispose() gets called if an exception is thrown.

This:

using (var foo = new DisposableThing())
{
    foo.DoSomething();
}

Is equivalent to:

var foo = new DisposableThing();

try
{
    foo.DoSomething();
}
finally
{
    foo.Dispose();
}

If you already have a try-catch, just tag a finally at the end and avoid the using statement alltogether.

var scope = new TransactionScope();

try
{
    DataBaseStuff();
    scope.Complete();
}
catch (Exception ex)
{
    LogError(ex);
}
finally
{
    scope.Dispose();
}

The using statement isn't some brain-dead best practice; it is syntactic sugar allowing you to clearly define the scope of the disposable resource and have the compiler fill in the finally { foo.Dispose(); } code for you. It's a shortcut, not a law.

Another option is to use an inline using statement:

using var scope = new TransactionScope();

try
{
    // do database stuff
    scope.Complete();
}
catch (Exception ex)
{
    // log exception
}

Another idea:

using (var scope = new TransactionScope())
try
{
    //
}
catch (Exception ex)
{
    //
}

Smoosh the using statement above the try with no curly braces. This takes advantage of the fact curly braces for the using statement are optional, and act like an if statement with no braces; the next line of code is implicitly part of the block, and since the try-catch is its own block, the compiler puts them all together without the need for additional braces or indentation. The disadvantage here is that it becomes less obvious what is in scope for the using statement. This code construct isn't used often, so it might violate the Principal of Least Astonishment as well.

The inline version of the using statement just calls Dispose() at the end of the method, essentially. I tend to favor the variation that avoids unnecessary levels of indentation, and using a finally block or inline using statements accomplish that. Inline using statements are a little more idiot-proof (you don't need to remember to call Dispose()) but this language feature might not be available if you are working in .NET Framework 4.x or .NET Standard 2.0. For those older framework versions, I would just use a finally block and call Dispose() on the object.

When working with exceptions (exceptional behavior) we should catch exception as early (may be never) as we know how to react properly.

try {
  ...
  using var scope = new TransactionScope();

  try {
    // Database specific 

    DataBaseStuff();
    scope.Complete();
  }
  catch (DbException ex) { // <- Note that we catch DbException, not Exception
    // So the database failes to commit the transaction and we know what to do with this.
    // In this particular case we should throw the transaction away and do nothing
    // (We could have repeated the transaction, put data into te log to apply it later etc.)
    LogError(ex);
  }

  ...
}
catch (Exception ex) { 
  // Ehere we face unexpected exception (say, Out Of Memory), let's log it 
  LogError(ex);

  // And then, probably, we should re-throw it to let system die:
  // Exception is unexpected, so we can't guarantee the system state and health
  throw;
}

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.