Вход/Регистрация
C# для профессионалов. Том II
вернуться

Ватсон Карли

Шрифт:

return true;

 }

 // Этот код выполняется, если встречается ошибка.

 catch (Exception е) {

// Отменить работу, которую выполнила эта функция.

ContextUtil.SetAbort;

return false;

 }

}

Что здесь происходит?

Мы имеем две транзакции, которые обрабатываются в зависимости от значения

CommitTrans
. Для любой транзакции
PlaceOrder
вызывает два метода, которые оба соединяющиеся с базой данных
Northwind
, чтобы сделать изменения в таблице
Product
. Метод
ReduceStock
сокращает объем запасов в столбце
UnitsInStock
, метод
IncreaseUnits
увеличивает значение столбца
UnitsOnOrder
. Для обоих методов первым параметром является
ProductID
в строке, которую нужно изменить, второй параметр есть величина, на которую мы хотим изменить соответствующий столбец.

Выполняющаяся транзакция контролируется булевой переменной

CommitTrans
, передаваемой в
PlaceOrder
. Первая транзакция должна быть зафиксирована, так как уровень запаса для
ProductID=2
равен 17, следовательно, можно удалить десять элементов и все еще иметь оставшийся запас. Однако вторая транзакция обречена на отказ так как
ProductID=5
не имеет запаса элементов и существует ограничение на столбец
UnitsInStock
, которое не позволяет значению становиться меньше нуля. Это означает, что можно проверить, будет ли транзакция отменяться или нет. Не должно быть никаких проблем с вызовом
IncreaseStock
, поэтому можно увидеть, что транзакция была отменена, проверяя значение столбца
UnitsOnOrder
для
ProductID=5
.

В блоке

try
, если все идет хорошо, или, другими словами, если поток выполнения должен покинуть
PlaceOrder
нормально, через
return true
, инструкция
PlaceOrder
вызывает метод
SetComplete
объекта
ContextUtil
, эффективно сообщая DTC через менеджер ресурсов, что в той части, которая касается его, транзакцию необходимо зафиксировать.

С другой стороны, если где-то в

PlaceOrder
возникает ошибка и порождается исключение, управление программой будет передано предложению
catch
. В этом предложении
PlaceOrder
вызовет метод
SetAbort
объекта
ContextUtil
. Этот метод посылает голос
PlaceOrder
за отмену транзакции, в которую он вовлечен, и DTC после получения этого голоса от менеджера ресурсов прикажет каждому участнику транзакции отменить свою работу.

Помните, что не требуется создавать экземпляр объекта

ContextUtil
, чтобы вызвать его методы
SetComplete
и
SetAbort
. Эти методы класса, поэтому их можно вызывать прямо на классе.

Практически любой код, поддерживающий транзакции будет походить на код в примере. Он вызывает

SetComplete
перед своей точкой выхода для фиксации всей работы, которая была успешно выполнена, или он вызывает метод
SetAbort
класса
ContextUtil
в своем обработчике ошибок, чтобы все отменить в связи с ошибкой. Существует, правда, еще более простой способ.

Компания Microsoft предоставляет атрибут .NET, называемый

AutoComplete
. Методы, модифицированные с помощью этого атрибута, автоматически применяют подход, описанный выше. И хотя такие методы никогда явно не ссылаются на класс
ContextUtil
, они неявно завершают свои транзакции, если те заканчиваются нормально, или отменяют всю работу если выход происходит в связи с ошибкой (когда порождается исключение). По прежнему необходимо вызывать
SetAbort
, чтобы отменить работу транзакции если порождается исключение.

[AutoComplete]

public bool PlaceOrder(bool CommitTrans) {

 try {

if (CommitTrans) {

// Эта транзакция должна быть зафиксирована

// шаг 1 — Увеличить число единиц продукта ID=2 на 10

IncreaseUnits(2, 10);

// шаг 2 - Сократить запас продукта ID=2 на 10 единиц

ReduceStock(2, 10);

} else {

// Эта транзакция должна быть отменена

// шаг 1 - Увеличить число единиц продукта ID=5 на 5

IncreaseUnits(5, 5);

// шаг 2 — Сократить запас продукта ID=5 на 5 единиц

ReduceStock(5, 5);

}

return true;

 } catch (Exception e) {

ContextUtil.SetAbort;

return false;

 }

}

Это полный код примера всей транзакции, он показывает, как все части объединяются. Следующее просто встроено в библиотеку классов с заданным сильным именем и зарегистрировано в глобальном кэше сборок.

using System;

using System.EnterpriseServices;

using System.Data.SqlClient;

namespace OrderTransaction {

 [Transaction(TransactionOptiоn.Required)]

 public class Purchase : ServicedComponent {

  • Читать дальше
  • 1
  • ...
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: