C#. ADO .NET. Присоединенный режим. Класс DbTransaction. Использование транзакций

Присоединенный режим (connected mode). Класс DbTransaction. Использование транзакций

Перед изучением данной темы рекомендуется ознакомиться со следующими темами:


Поиск на других ресурсах:


Содержание


1. Класс DbTransaction. Общие сведения

Если при работе с базами данных используются транзакции, то технология ADO .NET дает в распоряжение программиста ряд средств (классов, перечислений), основными из которых есть класс DbTransaction.

Класс DbTransaction используется, если в команде SQL, изменяющей данные, требуется зафиксировать или отменить транзакцию. Как известно, изменения в данных вносят команды типа:

  • INSERT – вставка новой строки в базу данных;
  • UPDATE – обновление строки;
  • DELETE – удаление строки.

Фиксацию или отмену транзакции выполняют методы Commit() и Rollback(), описанные в п. 2.

Из класса DbTransaction унаследованы классы конкретных провайдеров:

  • SqlTransaction;
  • OleDbTransaction;
  • OdbcTransaction.

Эти классы напрямую используются при программировании задач, связанных с обработкой транзакций.

 

2. Методы класса DbTransaction. Обзор

В каждом классе провайдера, который соответствует транзакции, реализованы три базовых метода:

  • Rollback() – откатывает транзакцию из состояния ожидания;
  • Commit() – фиксирует транзакцию в базе данных;
  • Save() – создает точку сохранения в транзакции, которая может использоваться для отката части транзакции и задает имя точки сохранения.

Сигнатура этих методов в классах SqlTransaction, OleDbTransaction, OdbcTransaction следующая:

void Rollback();
void Rollback(string transactionName);
void Commit();
void Save(string savePointName);

здесь

  • savePointName – имя точки сохранения;
  • transactionName – имя точки сохранения, в которую откатывается транзакция при вызове метода Rollback().

Как видно из реализаций методов, средства C# ADO .NET позволяют запоминать точку сохранения, в которую может быть выполнен откат транзакции.

 

3. Свойство Connection. Соединение с базой данных

Также в классе DbTransaction реализовано свойство Connection. Это свойство возвращает объект соединения, связанный с транзакцией или null, если транзакция больше не действительна. Объявление свойства для разных провайдеров следующее:

SqlConnection SqlTransaction.Connection { get; }
OleDbConnection OleDbTransaction.Connection { get; }
OdbcConnection OdbcTransaction.Connection { get; }

 

4. Пример работы с транзакциями (на примере SQL-сервера)

Для работы с транзакциями сервера MS SQL Server используется класс SqlTransaction.

Чтобы выполнить команду в SqlTransaction, нужно задать свойство Transaction в объекте класса SqlCommand.

Объект SqlTransaction создается с помощью способа BeginTransaction() класса SqlConnection.

После начала SqlTransaction для класса SqlConnection должны быть выполнены все запросы к транзакции. В противном случае возникнет исключительная ситуация InvalidOperationException с соответствующим сообщением.

Для фиксации данных в базе данных выполняется метод Commit() класса SqlTransaction. Для отката транзакции следует вызвать метод Rollback().

Демонстрируется метод, выполняющий транзакцию INSERT для заданного соединения

// Метод, выполняющий транзакцию INSERT -
void ExecuteSqlTransaction2(SqlConnection connection)
{
  // Изменить имя группы
  // 1. Объявить внутренние переменные
  int rows; // количество измененных строк

  // 2. Сформировать текст SQL-запроса изменения таблицы
  //   Старое имя группы: textBox1
  //   Новое имя группы: textBox2
  string sqlText = "INSERT INTO [Group] (NameGroup) VALUES (\'" +
    textBox1.Text + "\')";

  // 4. Изменить имя группы в базе данных
  try
  {
    // 4.1. Открыть соединение
    connection.Open();

    // 4.2. Создать транзакцию
    using (SqlTransaction transaction =
      connection.BeginTransaction()) // метод BeginTransaction()
    {
      // Создать объект с SQL-коммандой
      SqlCommand command = new SqlCommand(sqlText, connection, transaction);

      // Заполнить rows
      rows = command.ExecuteNonQuery();

      // Зафиксировать изменения в базе данных
      transaction.Commit();

      // transaction.Rollback(); - выполнить откат транзакции

      label2.Text = rows.ToString();
    }
  }
  catch (SqlException ex)
  {
    MessageBox.Show(ex.Message);
  }
  finally
  {
    // 4.5. Закрыть соединение
    connection.Close();

   // команда SELECT * FROM [Group]
   ExecuteSqlCommandSelectGroup(connection);
  }
}

 

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

Демонстрируется упрощенный пример выполнения SQL-запроса с поддержкой транзакции, вносящей дополнительную строку в таблицу Product базы данных с именем MyDatabase.

Таблица имеет следующие поля

ID_Product Name Price Count Date Note

Назначение полей таблицы следующее:

  • ID_Product – уникальный идентификатор, код товара.
  • Name – название товара;
  • Price – стоимость товара;
  • Count – количество единиц товара;
  • Date – дата получения товара;
  • Note – дополнительное описание (примечание) товара.

Нижеследующий фрагмент кода отображает создание и фиксирование транзакции для приложения типа Windows Forms (обработчик события клика на кнопке).

private void button10_Click(object sender, EventArgs e)
{
  // 1. Создать строку Connection String
  SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder();
  sb.DataSource = "(localdb)\\ProjectModels";
  sb.InitialCatalog = "MyDatabase";
  sb.IntegratedSecurity = true;

  // 2. Создать соединение на основе Connection String
  SqlConnection connection = new SqlConnection(sb.ConnectionString);

  // 3. Открыть соединение
  connection.Open();

  // 4. Создать транзакцию на основе соединения
  SqlTransaction transaction = connection.BeginTransaction();

  // 5. Создать команду на языке SQL с транзакцией
  string sqlCmd = "INSERT INTO Product (ID_Product, [Name], [Price], [Count], [Date], [Note]) " +
    "VALUES (16, 'Multicooker Bosh', 6500.00, 3, '2022-04-12', 'Bosh DT-280A')";
  SqlCommand command = new SqlCommand(sqlCmd, connection);

  // 6. Добавить транзакцию к команде sqlCmd
  command.Transaction = transaction;

  // 7. Выполнить инструкцию Transact-SQL для заданного подключения,
  //    возвращается количество измененных строк
  int rowsAffected = command.ExecuteNonQuery();

  // 8. Зафиксировать транзакцию
  command.Transaction.Commit();

  // 9. Вывести количество измененных строк
  label1.Text = "Rows affected = " + rowsAffected.ToString();

  // 10. Закрыть соединение
  connection.Close();
}

Объект, реализующий транзакцию для соединения connection, создается вызовом

SqlTransaction transaction = connection.BeginTransaction();

После этого этот объект добавляется к свойству Transaction объекта типа SqlCommand путем вызовов

SqlCommand command = new SqlCommand(sqlCmd, connection);
command.Transaction = transaction;

Для выполнения SQL-команды, представленной объектом command, применяется инструкция

command.ExecuteNonQuery();

Транзакция фиксируется с помощью вызова метода Commit(), как показано ниже

command.Transaction.Commit();

После этого вызова изменения фиксируются в базе данных.

Если после выполнения SQL-запроса необходимо отменить транзакцию, то вызывается метод Rollback()

command.Transaction.Rollback();

 

6. Пример создания точки сохранения и отката транзакции. Методы Save(), Rollback(string)

Точка сохранения задается с помощью метода

void Save(string savePointName);

здесь savePointName – имя этой точки сохранения.

Метод

void Rollback(string transactionName);

откатывает транзакцию из состояния ожидания и задает транзакцию или имя точки сохранения. Предварительно точка сохранения должна быть сохранена в методе Save().

Пример, демонстрирующий примерную последовательность действий при взаимодействии методов Save() и Rollback() следующая

// 1. Открыть соединение
connection.Open();

// 2. Создать транзакцию на основе соединения
SqlTransaction transaction = connection.BeginTransaction();

// 3. Создать команду на языке SQL с транзакцией
string sqlCmd = "................................"; // здесь задается текст команды

// 4. Создать объект SqlCommand
SqlCommand command = new SqlCommand(sqlCmd, connection);

// 5. Прибавить к команде sqlCmd транзакцию
command.Transaction = transaction;

// 6. Сформировать точку сохранения
string savePointName = "Save Point 1";
transaction.Save(savePointName);

// 7. Вызвать запрос, изменяющий базу данных
int rowsAffected = command.ExecuteNonQuery();

// 8. Здесь могут быть некоторые другие действия
// ...

// 9. Сделать откат транзакции к точке сохранения
transaction.Rollback(savePointName);

 


Связанные темы