Использование 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.IsolationLevel
Serializable
по умолчанию. В зависимости от приложения уровень изоляции можно понижать во избежание большого количества состязаний данных в приложении.
Примечание.
В рамках распределенных транзакций рекомендуется выполнять только операции обновления, вставки и удаления на удаленных серверах, поскольку они потребляют значительные ресурсы базы данных. Если операция будет выполнена на локальном сервере, распределенная транзакция не требуется, а локальная транзакция будет достаточной.
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();
}