Поделиться через


Локальные транзакции

Область применения: платформа .NET Framework .NET Standard

Скачать ADO.NET

Транзакции в ADO.NET используются, когда требуется связать несколько задач так, чтобы они выполнялись как одна единица работы. Например, пусть приложение выполняет две задачи. Во-первых, оно заносит в таблицу сведения о заказе. Во-вторых, обновляет таблицу, содержащую список товаров на складе, списывая заказанные элементы. При сбое любой задачи будет выполнен откат обоих изменений.

Определение типа транзакции

Транзакция считается локальной, если она состоит из одной фазы и обрабатывается непосредственно базой данных. Транзакция считается распределенной, если она координируется монитором транзакций и использует для разрешения транзакций резервные механизмы (например, двухфазную фиксацию).

Поставщик данных Microsoft SqlClient для SQL Server использует собственный объект SqlTransaction для выполнения локальных транзакций в базах данных SQL Server. Другие поставщики данных .NET также имеют собственные объекты Transaction. Кроме того, существует класс DbTransaction, доступный для написания независимого от поставщика кода с использованием транзакций.

Примечание.

Транзакции наиболее эффективны, когда выполняются на сервере. При работе с базой данных SQL Server, интенсивно использующей явные транзакции, следует рассмотреть возможность их записи в виде хранимых процедур при помощи инструкции Transact-SQL BEGIN TRANSACTION.

Выполнение транзакции с помощью одного подключения

В ADO.NET управление транзакциями осуществляется с помощью объекта Connection. Инициировать транзакцию можно с помощью метода BeginTransaction. После начала транзакции при помощи свойства Transaction объекта Command к ней можно прикрепить команду. Затем в зависимости от успеха или ошибки компонентов транзакции можно зафиксировать или откатить изменения, сделанные в источнике данных.

Примечание.

Метод EnlistDistributedTransaction не должен использоваться для локальной транзакции.

Область действия транзакции ограничена соединением. В следующем примере выполняется явная транзакция, состоящая из двух отдельных команд в блоке try. Команды выполняют инструкции INSERT для таблицы Production.ScrapReason в образце базы данных SQL Server AdventureWorks, которые будут зафиксированы при отсутствии исключений. Код в блоке catch откатит транзакцию, если возникнет исключение. При отмене транзакции или обрыве соединения до выполнения транзакции она откатывается автоматически.

Пример

Чтобы осуществить транзакцию, выполните указанные ниже действия.

  1. Вызовите метод BeginTransaction объекта SqlConnection для отметки начала транзакции. Метод BeginTransaction возвращает ссылку на транзакцию. Эта ссылка назначается объектам SqlCommand, прикрепленным к транзакции.

  2. Присвойте объект Transaction свойству Transaction объекта SqlCommand. Исключение вызывается, если команда выполняется при соединении с активной транзакцией, а объект Transaction не был назначен свойству Transaction объекта Command.

  3. Выполните требуемые команды.

  4. Для выполнения транзакции вызовите метод Commit объекта SqlTransaction, для завершения транзакции вызовите метод Rollback. Транзакция откатывается, если соединение закрывается или пропадает до выполнения метода Commit либо Rollback.

В следующем примере кода демонстрируется логика транзакций с использованием поставщика данных Microsoft SqlClient для SQL Server.

using System;
using Microsoft.Data.SqlClient;

class Program
{
    static void Main(string[] args)
    {
        string connectionString = "Data Source = localhost; Integrated Security = true; Initial Catalog = AdventureWorks";

        using (SqlConnection connection = new SqlConnection(connectionString))
        {
            connection.Open();

            // Start a local transaction.
            SqlTransaction sqlTran = connection.BeginTransaction();

            // Enlist a command in the current transaction.
            SqlCommand command = connection.CreateCommand();
            command.Transaction = sqlTran;

            try
            {
                // Execute two separate commands.
                command.CommandText =
                  "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong size')";
                command.ExecuteNonQuery();
                command.CommandText =
                  "INSERT INTO Production.ScrapReason(Name) VALUES('Wrong color')";
                command.ExecuteNonQuery();

                // Commit the transaction.
                sqlTran.Commit();
                Console.WriteLine("Both records were written to database.");
            }
            catch (Exception ex)
            {
                // Handle the exception if the transaction fails to commit.
                Console.WriteLine(ex.Message);

                try
                {
                    // Attempt to roll back the transaction.
                    sqlTran.Rollback();
                }
                catch (Exception exRollback)
                {
                    // Throws an InvalidOperationException if the connection
                    // is closed or the transaction has already been rolled
                    // back on the server.
                    Console.WriteLine(exRollback.Message);
                }
            }
        }
    }
}

См. также