Язык программирования C#9 и платформа .NET5
Direction = ParameterDirection.Input};cmdInsert.Parameters.Add(parameterId2);cmdInsert.Parameters.Add(parameterFirstName);cmdInsert.Parameters.Add(parameterLastName);// Это будет получено из объекта подключения.SqlTransaction tx = null;try{tx = _sqlConnection.BeginTransaction();// Включить команды в транзакцию.cmdInsert.Transaction = tx;cmdUpdate.Transaction = tx;// Выполнить команды.cmdInsert.ExecuteNonQuery();cmdUpdate.ExecuteNonQuery();// Эмулировать ошибку.if (throwEx){throw new Exception("Sorry! Database error! Tx failed...");// Возникла ошибка, связанная с базой данных! Отказ транзакции...}// Зафиксировать транзакцию!tx.Commit();}catch (Exception ex){Console.WriteLine(ex.Message);// Любая ошибка приведет к откату транзакции.// Использовать условную операцию для проверки на предмет null.tx?.Rollback();}finally{CloseConnection();}}Здесь используется входной параметр типа
, который указывает, нужно ли генерировать произвольное исключение при попытке обработки проблемного клиента. Такой прием позволяет эмулировать непредвиденные обстоятельства, которые могут привести к неудачному завершению транзакции. Понятно, что это делается лишь в демонстрационных целях; настоящий метод транзакции не должен позволять вызывающему процессу нарушать работу логики по своему усмотрению!boolОбратите внимание на применение двух объектов
для представления каждого шага транзакции, которая будет запущена. После получения имени и фамилии клиента на основе входного параметраSqlCommandс помощью методаcustomerIDобъекта подключения можно получить допустимый объектBeginTransaction(). Затем (что очень важно) потребуется привлечь к участию каждый объект команды, присвоив его свойствуSqlTransactionполученного объекта транзакции. Если этого не сделать, то логика вставки и обновления не будет находиться в транзакционном контексте.TransactionПосле вызова метода
на каждой команде генерируется исключение, если (и только если) значение параметраExecuteNonQuery()равноbool. В таком случае происходит откат всех ожидающих операций базы данных. Если исключение не было сгенерировано, тогда в результате вызоваtrueоба шага будут зафиксированы в таблицах базы данных.Commit()Тестирование транзакции базы данных
Выберите одного из клиентов, добавленных в таблицу
(например,Customers,Dave Benner). Добавьте вId = 1внутри проектаProgram.csновый метод по имениAutoLot.Client:FlagCustomer()void FlagCustomer(){Console.WriteLine("***** Simple Transaction Example *****\n");// Простой способ позволить транзакции успешно завершиться или отказать.bool throwEx = true;Console.Write("Do you want to throw an exception (Y or N): ");// Хотите ли вы сгенерировать исключение?var userAnswer = Console.ReadLine();if (string.IsNullOrEmpty(userAnswer) ||userAnswer.Equals("N",StringComparison.OrdinalIgnoreCase)){throwEx = false;}var dal = new InventoryDal();// Обработать клиента 1 - ввести идентификатор клиента,// подлежащего перемещению.dal.ProcessCreditRisk(throwEx, 1);Console.WriteLine("Check CreditRisk table for results");// Результаты ищите в таблице CreditRiskConsole.ReadLine();}Если вы запустите программу и укажете на необходимость генерации исключения, то обнаружите, что фамилия клиента в таблице
не изменилась, т.к. произошел откат всей транзакции. Однако если исключение не генерировалось, тогда окажется, что фамилия клиента в таблицеCustomersизменилась и была добавлена в таблицуCustomers.CreditRisksВыполнение массового копирования с помощью ADO.NET
В случае, когда необходимо загрузить много записей в базу данных, показанные до сих пор методы будут довольно неэффективными. В SQL Server имеется средство, называемое массовым копированием, которое предназначено специально для таких сценариев, и в ADO.NET для него предусмотрена оболочка в виде класса
. В настоящем разделе главы объясняется, как выполнять массовое копирование с помощью ADO.NET.SqlBulkCopy