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

TransactionScope ожидает вызов к своему Полному методу следующим образом. Иначе транзакция не будет фиксироваться.

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

    scope.Complete();
}

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

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

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

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

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

Я интересуюсь получением дальнейшего понимания, почему эта реализация использовалась.

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

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

transaction
{
    /* Perform transactional work here */

     if(problemOccurred)
     {
         rollback;
     }
}

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

10
задан Scott Munro 4 January 2010 в 14:53
поделиться

4 ответа

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

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

14
ответ дан 3 December 2019 в 14:11
поделиться

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

.
3
ответ дан 3 December 2019 в 14:11
поделиться

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

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

Что больше кода.

Правка:

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

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

.
15
ответ дан 3 December 2019 в 14:11
поделиться

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

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

.
4
ответ дан 3 December 2019 в 14:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: