Подтвердить что ты не робот

NHibernate с TransactionScope

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

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

с этим?:

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

Ответ 1

Я использую nHibernate 2.1 на некоторое время, и после нескольких производственных проблем и тестирования нескольких вариантов мы решили использовать следующий метод: Предотвращение утечки соединений с NHibernate И 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, нам приходилось использовать транзакцию ambient.

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

Ответ 2

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

Ответ 3

Вышеописанное работает нормально, если вы используете провайдера соединений, который поддерживает использование Light-weight Transaction Manager, например SQL Server 2005/2008.

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

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

Ответ 4

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

  • Используйте достаточно недавнюю версию NHibernate ( >= 3.1).
  • Основной поставщик данных ADO.NET должен поддерживать TransactionScope (ok для SQL-Server, Oracle >= 10 с ODP.NET).
  • Создайте свою NH-сессию в TransactionScope, чтобы убедиться, что она зачислена.
  • Ручка NHibernate flushing вручную. См. Также здесь и здесь.
  • Подготовьтесь к распределенным транзакциям. Если вы создаете несколько сеансов в одной области, первоначально локальная транзакция может быть повышена до распределенной транзакции. Я видел, что это происходит даже с теми же строками соединения в Oracle 11.2 DB с использованием ODAC 11.2.0.3.20. В SQL Server 2008 R2 он не продвигался. (BTW, это можно увидеть, просмотрев Transaction.Current.TransactionInformation.DistributedIdentifier, который является нулевым для локальных транзакций.) Хотя распределенные транзакции имеют некоторые преимущества, они дороже, и некоторые дополнительные боли создают их. (См. здесь, как это сделать для Oracle). Чтобы убедиться, что продвижение никогда не происходит в Oracle, установите "" Рекламная транзакция= локальная" в вашей строке подключения. Это создает исключение, если какой-то код пытается это сделать.

Я надеюсь, что все; -)

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

Ответ 5

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

Ответ 6

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

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

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