9

Я использую FluentNHibernate, и у меня есть список записей, сопоставленных с представлением SQL Server 2008. Грязные чтения в порядке со мной, а не блокировка таблиц является приоритетом.Использование TransactionScope с чтением uncommitted - с (nolock) в SQL необходимо?

SQL-запросов внутри вида, не имеет ни с (NOLOCK), однако, я использую следующий подход ...

 
using (var txScope = new TransactionScope(TransactionScopeOption.Suppress, new TransactionOptions() { IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted })) 
{ 
    ... The reading of records from the view is done here, through Fluent NHibernate... 
} 

ли установка уровня изоляции на уровне приложений для чтения незавершенных, применять с (nolock) к запросам, которые генерируются в этом контексте?

ответ

11

Короткий ответ: Нет

Длинный ответ:

Просто определение TransactionScope не определяет, что любое чтение или запись будет вызываться в рамках транзакции.

Чтобы выполнить что-то в рамках транзакции, вам все равно придется открывать и совершать транзакции!

TransactionOptions из TransactionScope для Timeout и IsolationLevel просто определить значения по умолчанию для любой сделки, созданной в рамках без этих опций явно установлены. Фактически TransactionScope создает транзакцию, но она не будет активной без открытия новой транзакции. Внутри это будет делать некоторые сложные вещи, клонируя транзакцию и т. Д., Поэтому давайте проигнорируем это ...

Без транзакции вы не можете определить уровень изоляции, любой оператор select будет выполняться с IsolationLevel.ReadCommitted, поскольку это значение по умолчанию SQL Server.

Вы также можете запросить session.Transaction.IsActive, чтобы узнать, активна ли транзакция для сеанса!

Давайте посмотрим на следующий код, я ставлю некоторые комментарии, чтобы сделать его немного более ясно

using (var scope = new TransactionScope(TransactionScopeOption.Required, 
        new TransactionOptions() 
        { 
         IsolationLevel = IsolationLevel.ReadUncommitted 
        })) 
{ 

    using (var session = sessionFactory.OpenSession()) 
    { 
     // outside any transaction... 
     var x = session.Transaction.IsActive; // false; 

     // read will be done with SQL Server default (ReadCommited) 
     var pp = session.Query<Page>().Where(p => p.Photos.Count() > 1).ToList(); 

     using (var transaction = session.BeginTransaction()) 
     { 
      // will use ReadUncommitted according to the scope 
      var y = session.Transaction.IsActive; // true; 

      var p1 = session.Get<Page>(1); 

      transaction.Commit(); 
     } 
     using (var transaction = session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted)) 
     { 
      // will use ReadCommitted according to the transaction initialization 
      var y = session.Transaction.IsActive; // true; 

      var p1 = session.Get<Page>(1); 

      transaction.Commit(); 
     } 

     scope.Complete(); 
    } 
} 

Вы также можете посмотреть, как SQL Server реагирует на эти настройки с помощью SQL Server Profiler.

Просто создайте новую трассировку и следить за Audit Login события, текст мероприятия будет включать в себя уровень изоляции, и вы можете видеть, что он на самом деле делает Audit Login каждый раз, когда создается транзакция, например

set transaction isolation level read uncommitted 

-

Пожалуйста, поправьте меня, если какой-либо из этой информации может быть не так, я просто понял это сам, так что может быть некоторый потенциал разрушения;)

+0

Параметр 'Аудит login' не является надежным способом для просмотра текущего уровня изолированности выполняемые команды. См. Мой комментарий в [LINQ + TransactionScope не изменит уровень изоляции в SQL Server Profiler] (http://stackoverflow.com/questions/3911285/linq-transactionscope-will-not-change-isolation-level-in-sql-server -profiler). Изменение уровня изоляции трудно просмотреть в Profiler и может произойти между строкой входа в систему аудита и рассматриваемой операцией SQL. Это лучше всего объясняется в комментариях от _divega_ по адресу http://entityframework.codeplex.com/workitem/1712. – DeveloperRob

0

Я не уверен, почему, но код TransactionScope не работал для меня.

Я использовал этот код. После запуска нового сеанса убедитесь, что у вас уже нет существующей транзакции.(Есть и другие способы сделать это, конечно)

 using (var session = _session.SessionFactory.OpenSession()) 
     using (var txn = session.BeginTransaction(IsolationLevel.ReadUncommitted)) 
     { 
      // bunch of select statements. 
     } 

В NHibernate Profiler я мог видеть это:

begin transaction with isolation level ReadUncommitted 
+0

Ha! Забавно, когда это происходит. Оказывается, у меня была транзакция, которая была слишком большой в моей пакетной работе. Я собрал транзакцию, и теперь мне больше не нужно грязное чтение. (READUNCOMMITTED) – Jess

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