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


Использование System.Transactions

Область применения:SQL Server

Пространство имен System.Transactions предоставляет платформу транзакций, которая полностью интегрирована с интеграцией ADO.NET и средой CLR SQL Server. Класс System.Transactions.TransactionScope делает транзакционный блок кода неявным путем перечисления подключений в распределенную транзакцию. Необходимо вызвать метод Complete в конце блока кода, помеченного TransactionScope. Метод Dispose вызывается, когда выполнение программы покидает блок кода, что приводит к прекращению транзакции, если метод Complete не вызывается. Если исключение было вызвано тем, что код покидает область действия, транзакция считается прекращенной.

Рекомендуется использовать блок using, чтобы убедиться, что метод Dispose вызывается в объекте TransactionScope при выходе блока using. Сбой фиксации или отката ожидающих транзакций может серьезно снизить производительность, так как время ожидания по умолчанию для TransactionScope составляет одну минуту. Если вы не используете инструкцию using, необходимо выполнить все действия в блоке Try и явно вызвать метод Dispose в блоке Finally.

Если исключение возникает в TransactionScope, транзакция помечается как несогласованная и отказывается. Он откатывается, когда TransactionScope удаляется. Если исключений не возникает, то участвующие транзакции будут зафиксированы.

TransactionScope следует использовать только при доступе к локальным и удаленным источникам данных или внешним диспетчерам ресурсов, так как TransactionScope всегда вызывает повышение уровня транзакций, даже если оно используется только в контекстном соединении.

Класс TransactionScope создает транзакцию с System.Transactions.Transaction.IsolationLevelSerializable по умолчанию. В зависимости от приложения уровень изоляции можно понижать во избежание большого количества состязаний данных в приложении.

Примечание.

В рамках распределенных транзакций рекомендуется выполнять только операции обновления, вставки и удаления на удаленных серверах, поскольку они потребляют значительные ресурсы базы данных. Если операция будет выполнена на локальном сервере, распределенная транзакция не требуется, а локальная транзакция будет достаточной. SELECT инструкции могут блокировать ресурсы базы данных ненужным образом, и в некоторых сценариях может потребоваться использовать транзакции для выбора. Любые не связанные с базой данных действия должны выполняться за пределами области транзакции, если только в ней не задействованы другие диспетчеры ресурсов транзакций.

Хотя исключение в пределах транзакции предотвращает фиксацию транзакции, класс TransactionScope не имеет подготовки к откату любых изменений, внесенных в код за пределами области самой транзакции. Если необходимо выполнить некоторые действия при откате транзакции, необходимо написать собственную реализацию интерфейса System.Transactions.IEnlistmentNotification и явно включить в транзакцию.

Примеры

Чтобы работать с System.Transactions, необходимо иметь ссылку на файл System.Transactions.dll.

В следующем коде показано, как создать транзакцию, которую можно повысить в двух разных экземплярах SQL Server. Эти экземпляры представлены двумя разными объектами System.Data.SqlClient.SqlConnection, которые упаковываются в блок TransactionScope. Код создает блок TransactionScope с помощью инструкции using и открывает первое соединение, которое автоматически заверяет его в TransactionScope. Изначально транзакция прикрепляется как упрощенная, а не полностью распределенная транзакция. Код предполагает существование условной логики (опущено для краткости). Он открывает второе подключение только в том случае, если оно необходимо, завербовав его в TransactionScope.

При открытии второго соединения транзакция автоматически повышается до полностью распределенной. Затем код вызывает TransactionScope.Complete, которая фиксирует транзакцию. Код удаляет два подключения при выходе из операторов using для подключений. Метод TransactionScope.Dispose для TransactionScope автоматически вызывается при завершении блока using для TransactionScope. Если исключение было создано в любой момент в блоке TransactionScope, Complete не вызывается, а распределенная транзакция откатывается при удалении TransactionScope.

using (TransactionScope transScope = new TransactionScope())
{
    using (SqlConnection connection1 = new
       SqlConnection(connectString1))
    {
        // Opening connection1 automatically enlists it in the
        // TransactionScope as a lightweight transaction.
        connection1.Open();

        // Do work in the first connection.

        // Assumes conditional logic in place where the second
        // connection will only be opened as needed.
        using (SqlConnection connection2 = new
            SqlConnection(connectString2))
        {
            // Open the second connection, which enlists the
            // second connection and promotes the transaction to
            // a full distributed transaction.
            connection2.Open();

            // Do work in the second connection.
        }
    }
    //  The Complete method commits the transaction.
    transScope.Complete();
}