Почему TransactionScope не имеет успеха?

TransactionScope ожидает вызова своего метода Complete следующим образом. В противном случае транзакция не будет выполнена.

using(TransactionScope scope = new TransactionScope())
{
    /* Perform transactional work here */

    scope.Complete();
}

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

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

using(TransactionScope scope = new TransactionScope())
{
    /* Perform transactional work here */

     if(problemOccurred)
     {
         scope.Rollback();
     }
}

Обратите внимание, что флаг "Описанная проблема" требуется только в тех случаях, когда проблема не привела к исключению. В этом случае откат будет выполняться автоматически.

Мне интересно узнать, почему эта реализация была использована.

Обновление:. Несколько ответов до сих пор утверждали, что блок try-catch был бы необходим, если бы использовалась реализация, которую я описал. Это не тот случай. Транзакция автоматически откатывается, когда исключение не обрабатывается в блоке использования. Это касается как существующей реализации, так и той, которую я описал. Дополнительную информацию см. В разделе "Завершение области транзакции" здесь.

Обновление 2: Я, наконец, понимаю, что объясняется в ответах. Это не языковая конструкция, которая могла быть интерпретирована любым способом, который разработчики языка считали нужным - это реализация шаблона IDisposable. Без вызова для завершения кода в методе Dispose не было бы известно, будет ли он вызван в результате успешного выполнения кода в используемом блоке или из-за возникновения исключения. Я представлял что-то похожее на следующее, где и транзакция, и откат являются ключевыми словами.

transaction
{
    /* Perform transactional work here */

     if(problemOccurred)
     {
         rollback;
     }
}

Это, конечно, представляет проблемы, если параметры транзакции должны быть переданы TransactionScope.

Ответ 1

Это означает, что вам не нужно вводить блок try/finally (или catch) вручную (возможно, с флагом успеха) для случая сбоя. Попробуйте переписать вышеприведенный код, чтобы опрокинуться на ошибку и посмотреть, насколько беспорядочно это...

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

Ответ 2

Таким образом, каждая транзакция будет выглядеть так:

using(TransactionScope scope = new TransactionScope())
{
  try
  {
    /* Perform transactional work here */
  }
  catch (Exception)
  {
    scope.Rollback();
    throw;
  }
}

Какой код больше.

Edit:

Все остальное - рискованный или плохой стиль. Вы должны быть абсолютно уверены, что при совершении не было ошибок. Когда вы покидаете блок использования, вы не знаете, оставите ли вы его, потому что выбрано исключение или потому, что вы только что закончили его. При вызове Complete вы знаете.

Синтаксис блока транзакций уже является простейшим, что вы можете сделать. Просто реализуйте транзакцию без специальной обработки ошибок и завершите ее в конце. Вам не нужно заботиться и откатываться, когда возникает какая-либо ошибка. Рассмотрим, что исключения могут быть выбраны почти в каждой строке кода (например, NullReference, Overflows, InvalidOperation и т.д.). Так что может быть проще, чем это?

Ответ 3

Если бы была выбрана другая реализация, тогда люди задавали бы обратный вопрос!

Серьезно, однако, поведение по умолчанию в механизме, предназначенном для защиты от частичных или неправильных обновлений, должно быть не для фиксации, не так ли?

Ответ 4

Я думаю, что количество кода для написания для успеха - это, как говорит @Jon Skeet, меньше (и менее уродливое) по текущему пути. Однако с точки зрения транзакций я бы подумал, что вы хотите быть пессимистичным и считаете, что, если только не было указано явно, что вы откажетесь обратно. По моему мнению, совершение транзакции с ошибкой является гораздо более сложной проблемой, чем случайная неудача совершения успешной транзакции из-за ошибки кода.