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


Локальные транзакции (ADO.NET)

Обновлен: November 2007

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

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

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

Для выполнения локальных транзакций каждый поставщик данных платформы .NET Framework имеет свой собственный объект Transaction. Если требуется выполнить транзакцию в базе данных SQL Server, выбирается транзакция System.Data.SqlClient. Для транзакции Oracle используйте поставщик System.Data.OracleClient. Кроме того, существует новый класс DbTransaction, доступный для написания независимого от поставщика кода с использованием транзакций.

2k2hy99x.alert_note(ru-ru,VS.90).gifПримечание.

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

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

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

2k2hy99x.alert_note(ru-ru,VS.90).gifПримечание.

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

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

Пример

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

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

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

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

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

Следующий пример кода демонстрирует транзакционную логику, используемую ADO.NET с Microsoft SQL Server.

Using connection As New SqlConnection(connectionString)
    connection.Open()

    ' Start a local transaction.
    Dim sqlTran As SqlTransaction = connection.BeginTransaction()

    ' Enlist a command in the current transaction.
    Dim command As SqlCommand = 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 ex As Exception
        ' Handle the exception if the transaction fails to commit.
        Console.WriteLine(ex.Message)

        Try
            ' Attempt to roll back the transaction.
            sqlTran.Rollback()

        Catch exRollback As Exception
            ' Throws an InvalidOperationException if the connection 
            ' is closed or the transaction has already been rolled 
            ' back on the server.
            Console.WriteLine(exRollback.Message)
        End Try
    End Try
End Using
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);
        }
    }
}

См. также

Основные понятия

Распределенные транзакции (ADO.NET)

Интеграция System.Transactions с SQL Server (ADO.NET)

Другие ресурсы

Транзакции и параллелизм (ADO.NET)