2015-02-06 2 views
4

Я читал об объеме операции в C# и как это работает:Как сделать код, например, «TransactionScope»?

using (connectionDb) 
{ 
    connectionDb.Open(); 
    using (var ts = new System.Transactions.TransactionScope()) 
    { <-- 
     try 
     { 
      connectionDb.ExecuteNonQuery(); 
      ts.Complete(); 
     } 
     catch (Exception) 
     { 
      throw; 
     } 
     finally 
     { } 
    } <-- 
} 

Каждые положения в с помощью скобок работает на одной и той же операции, но я не понимаю, как код определяет, что databasecommand являются работающий в области без прохождения области транзакции, не является ни открытием соединения, ни при выполнении запроса.

Например, если у меня есть следующий код:

var myObject = new MyObject(); 
var childObject = new ChildObject(); 
childObject.Foo(myObject); 
childObject.Bar(myObject); 

Могу ли я создать область для переменной myObject и использовать в методах childObject без передать ее с помощью параметра? например:

using(var myObject = new MyObject()) 
{ 
    childObject.Foo(); -- Here the method use the variable myObject 
    childObject.Bar(); -- Here the method use the variable myObject 
} 

ответ

7

При создании TransactionScope он хранится в статической переменной Transaction.Current, которая хранится в локальном хранилище потоков. Методы, которые взаимодействуют с транзакцией, рассматривают эту переменную для определения транзакции, в которой они находятся. Это называется внешней транзакцией.

+2

Просто пометьте свой статический атрибут ThreadStatic. – Jessica

+0

Я не знал этого атрибута ThreadStatic, +1 из-за этого. Это действительно полезная команда. –

+2

@OnlyaCuriousMind Будьте осторожны с 'ThreadStatic', хотя в нем есть несколько предостережений. Например, если вы назначаете значение по умолчанию, оно будет использоваться только для первого потока, из которого запускается статический конструктор, - другие потоки будут пустым (null/default) – Luaan

1

В этом примере показана внешняя транзакция. Под капотом соединение с базой данных обнаруживает, что вы инициировали транзакцию и занесете ее в нее. Другие процессы могут подключаться к этой транзакции (например, транзакционный обмен сообщениями MSMQ), так что, когда выполняется условие, которое приведет к откату, каждый другой завершенный процесс может инициировать откат. В зависимости от выбранного уровня изоляции он также будет применять более агрессивные блокировки данных. 1

Ваш второй бит кода будет охватывать объект, который вы определяете, но вариант использования отличается. Вы все еще должны сделать что-то вроде этого:

using(var myObject = new MyObject()) 
{ 
    childObject.Foo(myObject); -- Here the method use the variable myObject 
    childObject.Bar(myObject); -- Here the method use the variable myObject 
} 

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

+0

Посмотрите на ответ Джессики. –

Смежные вопросы