Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Добавление метода транзакции в InventoryDAL




Добавление таблицы CreditRisks в базу данных AutoLot

Основные члены объекта транзакции ADO.NET

Типы для работы с транзакциями существуют во всех библиотеках базовых классов, но мы будем рассматривать объекты транзакции, которые имеются в поставщиках данных ADO.NET — все они порождены от DBTransaction и реализуют интерфейс IDbTransaction. Вспомните, что IDbTransaction определяет ряд членов:

public interface IDbTransaction: IDisposable{ IDbConnection Connection { get; } IsolationLevel IsolationLevel { get; } void Commit(); void Rollback();}

Обратите внимание на свойство Connection, которое возвращает ссылку на объект подключения, инициировавший данную транзакцию (как мы увидим, объект транзакции можно получить от данного объекта подключения). Метод Commit() вызывается, если все операции в базе данных завершились успешно. При этом все ожидающие изменения фиксируются в хранилище данных. А метод Rollback() можно вызвать при возникновении исключения времени выполнения, чтобы сообщить СУБД, что все ожидающие изменения следует отменить и оставить первоначальные данные без изменений.

Свойство IsolationLevel объекта транзакции позволяет указать степень защиты транзакции от действий параллельных транзакций. По умолчанию транзакции полностью изолируются до их фиксации. Полную информацию о значениях перечисления IsolationLevel можно найти в документации по.NET Framework 4.0 SDK.

Кроме членов, определенных интерфейсом IDbTransaction, в типе SqlTransaction определен дополнительный член Save(), который предназначен для определения точек сохранения (save point). Эта концепция позволяет откатить неудачную транзакцию до указанной точки, не выполняя откат всей транзакции. При вызове метода Save() с помощью объекта SqlTransaction можно задать произвольный строковый псевдоним.

А при вызове Rollback() можно указать этот псевдоним в качестве аргумента, чтобы выполнить частичный откат (partial rollback). При вызове Rollback() без аргументов будут отменены все ожидающие изменения.

А теперь рассмотрим, как можно использовать транзакции в ADO.NET. Вначале откройте окно Server Explorer из Visual Studio 2010 и добавьте в базу данных AutoLot новую таблицу с именем CreditRisks, которая содержит точно такие же столбцы, что и таблица Customers, созданная ранее: CustID (первичный ключ), FirstName и LastName. Эта таблица предназначена для отсеивания нежелательных клиентов с плохой кредитной историей. После добавления новой таблицы в диаграмму базы данных AutoLot ее реализация будет такой:

Как и предыдущий пример с пересылкой денег с депозита на текущий счет, этот пример, где подозрительный клиент перемещается из таблицы Customers в таблицу CreditRisks, должен работать под недремлющим оком транзакционной области (ведь вы хотите запомнить идентификаторы и имена некредитоспособных клиентов). А именно, необходимо гарантировать, что либо будет выполнено успешное удаление текущих кредитных рисков из таблицы Customers с последующим их добавлением в таблицу CreditRisks, либо ни одна из этих операций не будет выполнена.

В производственной среде вам не понадобится создавать совершенно новую таблицу базы данных для подозрительных клиентов. Достаточно добавить в таблицу Customers логический столбец IsCreditRisk. Эта новая таблица предназначена просто для опробования работы с простыми транзакциями.

А теперь посмотрим, как работать с транзакциями ADO.NET программным образом. Откройте созданный ранее проект AutoLotDAL Code Library и добавьте в класс InventoryDAL новый общедоступный метод ProcessCreditRisk(), предназначенный для работы с кредитными рисками (в данном примере для простоты не используется параметризованный запрос, но в производственном методе его следует задействовать):

public void ProcessCreditRisk(bool throwEx, int custId) { // Выборка имени по идентификатору клиента string fName = string.Empty; string lName = string.Empty; SqlCommand cmdSelect = new SqlCommand(string.Format("Select * from Customers where CustID = {0}", custId), connect); using (SqlDataReader dr = cmdSelect.ExecuteReader()) { if (dr.HasRows) { dr.Read(); fName = (string)dr["FirstName"]; lName = (string)dr["LastName"]; } else return; } // Создание объектов команд для каждого шага операции. SqlCommand cmdRemove = new SqlCommand(string.Format("Delete from Customers where CustID = {0}", custId), connect); SqlCommand cmdInsert = new SqlCommand(string.Format("Insert Into CreditRisks" + "(CustID, FirstName, LastName) Values" + "({0}, '{1}', '{2}')", custId, fName, lName), connect); // Получаем из объекта подключения. SqlTransaction tx = null; try { tx = connect.BeginTransaction(); // Включение команд в транзакцию cmdInsert.Transaction = tx; cmdRemove.Transaction = tx; // Выполнение команд. cmdInsert.ExecuteNonQuery(); cmdRemove.ExecuteNonQuery(); // Имитация ошибки. if (throwEx) { throw new ApplicationException("Ошибка базы данных! Транзакция завершена неудачно."); } // Фиксация. tx.Commit(); } catch (Exception ex) { Console.WriteLine(ex.Message); // При возникновении любой ошибки выполняется откат транзакции. tx.Rollback(); } }

Здесь используется входной параметр типа bool, который указывает, нужно ли генерировать произвольное исключение при попытке обработки нежелательного клиента. Это позволит имитировать непредвиденные ситуации, которые могут привести к неудачному завершению транзакции. Понятно, что здесь это сделано лишь в демонстрационных целях; в реальности метод транзакции не должен позволять вызывающему процессу разрушать всю логику по своему усмотрению!

Мы используем два объекта SqlCommand, представляющие каждый шаг предстоящей транзакции. После получения имени и фамилии клиента по входному параметру custID с помощью метода BeginTransaction() объекта подключения получаем нужный объект SqlTransaction. Если этого не сделать, логика вставки/удаления не будет выполняться в транзакционном контексте.

Если (и только если) значение логического параметра равно true, то после вызова ExecuteNonQuery() для обеих команд генерируется исключение. В этом случае все ожидающие подтверждения операции базы данных аннулируются. Если исключение не было сгенерировано, оба шага фиксируются в таблицах базы данных при вызове Commit(). Скомпилируйте измененный проект AutoLotDAL и проверьте, нет ли ошибок.




Поделиться с друзьями:


Дата добавления: 2015-05-09; Просмотров: 410; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.012 сек.