Поддержка транзакции в языке SQL и библиотеках ADO.Net

Собственно, для использования транзакций в языке SQL имеется не так много инструкций. Тем не менее, в разных СУБД эта поддержка реализована несколько по-разному, так что описать общие для всех команды не представляется возможным. В нашем курсе мы опираемся на СУБД Microsoft SQL Server, поэтому в качестве примера возьмем эту систему.

По умолчанию, в SQL Server каждый запрос является отдельной транзакцией. Это так называемый режим автофиксации транзакций (autocommit mode). Если есть необходимость управлять транзакциями явным образом, этот режим может быть отключен при помощи команды SET IMPLICIT_TRANSACTIONS ON. Вернуться к режиму автофиксации можно выполнив ту же команду, но заменив ON на OFF.

Чтобы явным образом начать транзакцию, в SQL Server используется следующее выражение:

BEGIN TRAN[SACTION]

[[transaction_name]

[WITH MARK ['description']]]

Необязательный аргумент transaction_name позволяет задать имя транзакции, чтобы в дальнейшем обращаться к ней по этому имени. Опция WITH MARK позволяет задать описание для транзакции, которое попадет в журнал транзакций и может быть в дальнейшем использовано для выбора информации о конкретной транзакции.

По умолчанию, транзакции выполняются с уровнем изолированности READ COMMITTED. Если требуется использовать другой уровень изолированности, можно использовать следующую команду:

SET TRANSACTION ISOLATION LEVEL

{READ COMMITTED| READ UNCOMMITTED |REPEATABLE READ| SERIALIZABLE}

После выполнения команды все транзакции в данном сеансе будут выполняться с установленным уровнем изолированности.

После команды начала транзакции все остальные запросы будут выполняться в ее рамках. Можно запускать вложенные транзакции рамках уже запущенной. Синтаксис в этом случае не изменяется.

Для того, чтобы зафиксировать транзакцию, можно выполнить команду COMMIT [WORK]. После ее завершения все сделанные в рамках транзакции изменения данных будут внесены в БД.

SQL Server также поддерживает следующую команду фиксации:

COMMIT TRAN[SACTION] [transaction_name]

Здесь мы можем указать также имя фиксируемой транзакции. Фактически будет завершена последняя открытая транзакция, СУБД проигнорирует указанное имя, и указывают его программисты для себя, чтобы легче ориентироваться во вложенных транзакциях.

Аналогично выглядит и команда отката транзакции – ROLLBACK [WORK]. И точно также, SQL Server поддерживает вариант:

ROLLBACK TRAN[SACTION] [transaction_name]

По умолчанию, откатывается текущая транзакция, в случае, когда транзакции вложенные – самая внутренняя. Но имя транзакции здесь уже используется по назначению. Если оно указывается, это должно быть имя самой внешней транзакции, тогда она откатывается вместе со всеми вложенными в нее более мелкими транзакциями.

Последняя возможность при работе с транзакциями – это использование точек сохранения. Это промежуточные точки внутри транзакции, к которым можно вернуться, не отменяя транзакцию целиком. В SQL Server для установки точки сохранения используется следующий синтаксис:

SAVE TRAN[SACTION] savepoint_name

Savepoint_name – имя точки сохранения, которое надо использовать, чтобы выполнить откат до нее. Откат выполняется при помощи команды ROLLBACK TRANSACTION savepoint_name. После выполнения этой команды будет восстановлено состояние на точку сохранения.

Для использования транзакций в ADO.Net имеется специальный класс Transaction. Точнее говоря, соответствующие классы имеются для каждого провайдера данных. Для SQL Server класс называется SQLTransaction.

Класс имеет очень простой интерфейс. Для работы используются методы:

· Commit() - как легко догадаться, фиксирует транзакцию;

· Save(string SavepointName) - создает точку сохранения с переданным в качестве аргумента именем;

· Rollback() – откатывает транзакцию;

· Rollback(string SavepointName) – откатывает транзакцию до точки сохранения с заданным именем.

Чтобы начать транзакцию, необходимо вызвать метод BeginTransaction(string TransactionName) из объекта класса SQLConnection. Метод возвращает объект-транзакцию, в контексте которой можно выполнять команды. Чтобы выполнить команду в контексте транзакции, необходимо в свойство Transaction объекта SQLCommand записать ссылку на нужную транзакцию.

Приведем небольшой пример из документации к Visual Studio:

private static void ExecuteSqlTransaction(string connectionString)

{

using (SqlConnection connection = new SqlConnection(connectionString))

{

connection.Open();

SqlCommand command = connection.CreateCommand();

SqlTransaction transaction;

// Запускаем локальную транзакцию

transaction = connection.BeginTransaction("SampleTransaction");

// Мы должны задать для объекта Command оба свойства -

// и соединение, и транзакцию

command.Connection = connection;

command.Transaction = transaction;

try

{

command.CommandText =

"Insert into Region (RegionID, RegionDescription) VALUES (100, 'Description')";

command.ExecuteNonQuery();

command.CommandText =

"Insert into Region (RegionID, RegionDescription) VALUES (101, 'Description')";

command.ExecuteNonQuery();

// Попытка зафиксировать транзакцию.

transaction.Commit();

Console.WriteLine("Обе записи внесены в базу данных.");

}

catch (Exception ex)

{

//Здесь перехватываются исключения, возникающие в процессе

//выполнения и фиксирования транзакции.

Console.WriteLine("Commit Exception Type: {0}", ex.GetType());

Console.WriteLine(" Message: {0}", ex.Message);

// Попытка откатить транзакцию, в которой возникли ошибки.

try

{

transaction.Rollback();

}

catch (Exception ex2)

{

// В этом блоке перехватываются исключения, возникшие

// при попытке откатить транзакцию на сервере, например

// использование закрытого соединения.

Console.WriteLine("Rollback Exception Type: {0}", ex2.GetType());

Console.WriteLine(" Message: {0}", ex2.Message);

}

}

}

}

Из приведенного примера видно, как можно использовать транзакции в ADO.Net.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: