NHibernate с TransactionScope - PullRequest
       16

NHibernate с TransactionScope

33 голосов
/ 14 марта 2009

Может ли кто-нибудь дать мне краткий обзор использования TransactionScope с NHibernate? Нужно ли делать что-то особенное с помощью сеанса / IEnlistmentNotification / и т.д. заставить это работать? Есть ли какие-либо подводные камни, о которых я должен волноваться? Например, могу ли я заменить все мои транзакции гибернации:

var transaction = session.BeginTransaction();
try
{
    // code
    transaction.Commit();
}
catch (Exception)
{
    transaction.Rollback();
}

с этим?:

using (var scope = new TransactionScope())
{
    // code
    scope.Complete();
}

Ответы [ 6 ]

18 голосов
/ 03 ноября 2010

Я уже некоторое время использую nHibernate 2.1, и после нескольких проблем с производством и пробуя немало вариантов, мы остановились на следующем методе в соответствии с Предотвращение утечки соединений с помощью NHibernate And TransactionScope :

        using (var scope = new TransactionScope(TransactionScopeOption.Required))
        {
            using (var session = sessionFactory.OpenSession())
            using (var transaction = session.BeginTransaction())
            {
                // do what you need to do with the session
                transaction.Commit();
            }
            scope.Complete();
        }

Поскольку мы используем MSMQ и WCF, нам пришлось использовать транзакцию окружения.

Мы обнаружили, что не использование session.BeginTransaction () вызвало утечку соединения. Мы также обнаружили, что повторное использование сеанса после фиксации транзакции вызвало состояние гонки (nHibernate не является потокобезопасным, и DTSC-коммиты / откаты происходят в фоновом потоке).

7 голосов
/ 30 марта 2009

Я тестировал это с помощью разных поставщиков, и это просто работает. Если у вас нет «scope.Complete ()», то транзакция будет откатываться. Возможно, вам понадобится MSDTC, на котором запущены машины, если имеется более одного долговременного ресурса. В этом случае MSDTC автоматически обнаружит окружающие транзакции ADO.NET и будет управлять всем этим.

6 голосов
/ 06 июля 2009

Вышеуказанное работает нормально, если вы используете провайдер соединений, который поддерживает использование облегченного диспетчера транзакций, такого как SQL Server 2005/2008.

Если вы используете SQL Server 7/2000, то все ваши транзакции станут распределенными транзакциями, даже если вы нажмете только одну базу данных / ресурс. Это, вероятно, не то, что вы хотели бы в большинстве случаев, и будет дорогой производительности.

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

5 голосов
/ 28 февраля 2013

Я полагаю, что вы можете заменить транзакции NHibernate этим, если вы соблюдаете некоторые ограничения, как некоторые уже сказали:

  • Используйте относительно свежую версию NHibernate (> = 3.1 ).
  • Базовый поставщик данных ADO.NET должен поддерживать TransactionScope (нормально для SQL-сервера, Oracle> = 10 с ODP.NET).
  • Создайте сеанс NH в TransactionScope, чтобы обеспечить его зачисление.
  • Ручка NHibernate промывка вручную. Смотри также здесь и здесь .
  • Подготовка к распределенным транзакциям. Если вы создаете несколько сеансов в одной области, изначально локальная транзакция может быть преобразована в распределенную транзакцию. Я видел, как это происходит даже с теми же строками подключения в БД Oracle 11.2 с использованием ODAC 11.2.0.3.20. На SQL-Server 2008 R2 это не продвигалось. (Кстати, это можно увидеть, посмотрев Transaction.Current.TransactionInformation.DistributedIdentifier, который является нулевым для локальных транзакций.) Хотя распределенные транзакции имеют некоторые преимущества, они более дороги, и их установка требует дополнительных усилий. (См. здесь , как это сделать для Oracle). Чтобы продвижение в Oracle никогда не происходило, установите в строке подключения « Promotable Transaction = local». Это создает исключение, если какой-либо код пытается это сделать.

Надеюсь, это все; -)

PS: Я добавил детали Oracle, потому что они могут принести пользу моей заботе и другим.

1 голос
/ 14 сентября 2010

По словам Фабио Мауло в комментариях, связанных с NH-2107 :

Вы можете использовать TransactionScope, и вам также следует продолжить использование транзакции NH. Где вы читали, что использование TransactionScope означает избегание использования транзакции NH?

Я бы предположил, что явное использование транзакций NHibernate не обязательно, но, очевидно, это лучшая практика

1 голос
/ 16 ноября 2009

Также, если вы используете TransactionScope, обновитесь до NHibernate 2.1. Только с 2.1 NH действительно получил хорошую интеграцию с TransactionScope.

...