Необходим ли явный откат транзакции?

В многочисленных примерах, где говорится о явном откате транзакций базы данных, говорится следующее:

using (var transaction = ...)
{
    try
    {
        // do some reading and/or writing here

        transaction.Commit();
    }
    catch (SqlException ex)
    {
        // explicit rollback
        transaction.Rollback();
    }
}

Однако я, как правило, делаю это:

using (var transaction = ...)
{
    // do some reading and/or writing here

    transaction.Commit();
}

Когда возникает исключение, я просто полагаюсь на неявное откат транзакций, которые не выполняются.

Есть ли какие-либо проблемы, связанные с этим неявным поведением? У кого-нибудь есть убедительная причина, почему я не должен делать это таким образом?

Ответ 1

Нет, это не особенно необходимо, однако я могу думать о 2 причинах, почему это может быть хорошей идеей:

  • Ясность

Некоторые могут утверждать, что использование transaction.Rollback() делает его более ясным, при каких обстоятельствах транзакция не будет выполнена.

  • Освобождение блокировок

При работе с транзакциями важно реализовать определенные блокировки, которые будут выпущены только после откат или совершения транзакции. Если вы используете оператор using, тогда транзакция будет отклонена при удалении транзакции, однако если по какой-то причине вам необходимо выполнить некоторую обработку ошибок внутри блока using, может оказаться выгодным откат транзакции (удаление блокировок), прежде чем выполнять обработку сложных/временных затрат.

Ответ 2

Я вижу две проблемы с вашим использованием:

  • Вы полагаетесь на метод Dispose() транзакции для отката незафиксированной транзакции, создавая зависимость от сторонней реализации IDisposable. В этом случае это незначительный риск, но это не очень хорошая практика.
  • Вам не удастся зарегистрировать и/или обработать исключение. Кроме того, я бы выбрал Exception not SqlException.

Ответ 3

Думаю, на это можно ответить, что первый подход более читабельен для тех, кто поддерживает ваш код. Явный характер кодирования делает цели понятными и быстрыми. В то время как неявный откат вам понятен, и, возможно, любому, у кого есть более чем мимолетное знание обработки транзакций, может быть не для других. Тем не менее, несколько замечаний быстро исправили бы это. Единственная проблема заключается в том, что неявный откат не является документированной функцией объекта.

Итак, я бы сказал, предоставив вам комментарий к операции, и вы можете положиться на неявное действие, тогда нет веских оснований для явного подхода.

Ответ 4

Наиболее правильно написанное соединение ADO.NET будет выполнять транзакции отката, явно не переданные. Поэтому это не является строго необходимым.

Основное преимущество, которое я вижу в явном Rollback(), называет его возможностью установить там контрольную точку и затем проверить соединение или базу данных, чтобы увидеть, что происходит. Он также более ясен будущим разработчикам кода, что происходит под разными путями выполнения.

Ответ 5

Пока транзакция полностью автономна в блоке using(), вам хорошо идти. Проблемы могут возникать и возникают, однако, если кто-то, если вы передали существующий объект транзакции от вызывающего. Но это другой сценарий...