Открытие новой транзакции

Основной поток серверного вызова всегда выполняется в одной транзакции от начала и до конца:

server call

Исключение на любом этапе обработки запроса приведет к откату всей транзакции. Однако, выполнение DDL запросов (например, CREATE, ALTER, DROP) зафиксирует транзакцию, что может привести к нестабильному поведению системы. Поэтому такие запросы (DDL или же запросы, требующие промежуточной фиксации по иной причине) следует выполнять в отдельной транзакции.

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

Чтобы открыть новую транзакцию в рамках одного серверного вызова, следует использовать класс TransactionScopeBuilder (из пространства имен Ultima.Server.Data):

// Очистка содержимого таблицы.

using (var scope = TransactionScopeBuilder.CreateTransactionScope())

{

 var sql = @"DELETE TABLE TEMP_CALCULATIONS";

 SqlService.Execute(sql);

 scope.Complete();

}

В приведенном примере независимо от результатов серверного вызова весь блок внутри using будет зафиксирован в базе как единая операция.

Использование метода Complete указывает, что все операции в области успешно завершены. Использование метода Dispose завершает область транзакции, и если перед этим не был использован метод Complete, все операции в области откатываются.

Уровень изоляции созданной с помощью TransactionScopeBuilder транзакции будет read commited. Если необходимо создать транзакцию с уровнем изоляция serializable, можно использовать класс TransactionScope (подробное описание класса можно найти на сайте MSDN link eng/rus):

using (var ts = new TransactionScope(TransactionScopeOption.RequiresNew))

Однако рекомендуемым является первый вариант с TransactionScopeBuilder.