Проблема NHibernate TransactionScope с Oracle 11g - PullRequest
5 голосов
/ 22 сентября 2010

Следующий фрагмент кода отлично работает с SQL Server 2008 (SP1), но с Oracle 11g при вызове session.BeginTransaction () выдает исключение с сообщением «Соединение уже является частью локальной или распределенной транзакции» (трассировка стека) показано ниже). Использование "NHibernate.Driver.OracleDataClientDriver".

Кто-нибудь еще сталкивался с этим?

using (var scope = new TransactionScope())
{
   using (var session = sessionFactory.OpenSession())
   using (var transaction = session.BeginTransaction())
   {
      // do what you need to do with the session
      transaction.Commit();
    }
    scope.Complete();
}
     Exception at:    at NHibernate.Transaction.AdoTransaction.Begin(IsolationLevel isolationLevel)
           at NHibernate.Transaction.AdoTransaction.Begin()
           at NHibernate.AdoNet.ConnectionManager.BeginTransaction()
           at NHibernate.Impl.SessionImpl.BeginTransaction()
           at MetraTech.BusinessEntity.DataAccess.Persistence.StandardRepository.SaveInstances(List`1& dataObjects) in S:\MetraTech\BusinessEntity\DataAccess\Persistence\StandardRepository.cs:line 3103

        Inner error message was: Connection is already part of a local or a distributed transaction
        Inner exception at:    at Oracle.DataAccess.Client.OracleConnection.BeginTransaction(IsolationLevel isolationLevel)
           at Oracle.DataAccess.Client.OracleConnection.BeginDbTransaction(IsolationLevel isolationLevel)
           at System.Data.Common.DbConnection.System.Data.IDbConnection.BeginTransaction()
           at NHibernate.Transaction.AdoTransaction.Begin(IsolationLevel isolationLevel)

Ответы [ 4 ]

7 голосов
/ 27 июня 2011

Проблема с использованием только области транзакции описана здесь: NHibernate FlushMode, автоматическая очистка перед поиском

Появляется nhibernate (v3.1 с диалектом оракула и 11 г дБ с оп..net v2.112.1.2) требует собственных транзакций, чтобы избежать проблемы с очисткой, но я не смог заставить область транзакции работать с транзакциями nhibernate.

Кажется, я не могу ее получитьна работу :( это может быть дефект в nhibernate или odp.net, не уверен ...

обнаружил такую ​​же проблему здесь: NHibernate 3.0: TransactionScope и Auto-Flushing

ИСПРАВЛЕНО: найдено решение! Добавив «enlist = dynamic;» в мою строку соединения оракула, проблема была решена. Я смог использовать как транзакцию nhibernate (чтобы исправить проблему сброса), так и область транзакции, например, так:

        ISessionFactory sessionFactory = CreateSessionFactory();

        using (TransactionScope ts = new TransactionScope())
        {
            using (ISession session = sessionFactory.OpenSession())
            using (ITransaction tx = session.BeginTransaction())
            {
                //do stuff here

                tx.Commit();

            }
            ts.Complete();
        }

Я проверил свои файлы журналов и нашел это: 2011-06-27 14: 03: 59,852 [10] DEBUG NHibernate.Impl.AbstractSessionImpl - зачислен в транзакцию DTC: Serializable

до того, как какой-либо SQL был выполнен в соединении.Я проведу модульное тестирование, чтобы подтвердить правильность выполнения.Я не слишком уверен, что сериализуемый говорит мне, хотя

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

Ответ Brads с использованием внешнего TransactionScope и внутренней транзакции NHibernate с enlist = dynamic, похоже, не работает должным образом.Хорошо, данные передаются.

Но если вы опустите scope.Complete () или создадите исключение после tx.Commit (), данные все равно будут зафиксированы (для Oracle)!Однако по какой-то причине это работает для SQL-Server.

Транзакции NHibernate позаботятся об автоматической очистке, но в конце они вызывают основную транзакцию ADO.NET.В то время как многие источники рекомендуют использовать вышеприведенный шаблон в качестве наилучшей практики для решения проблемы автоматической очистки , , источники, обсуждающие нативный ADO.NET, говорят об обратном: НЕ используйте TransactionScope и внутренние транзакции вместе, не для Oracle идля SQL-сервера.(См. этот вопрос и мой ответ )

Мой вывод : не объединять транзакции TransactionScope и NHibernate.Чтобы использовать TransactionScope, пропустите транзакции NHibernate и обработайте сброс вручную (см. Также NHibernate Flush doc ).

0 голосов
/ 03 марта 2015

Из поваренной книги NHibernate

Помните, что NHibernate требует транзакцию NHibernate при взаимодействии с базой данных.TransactionScope не является заменой. Как показано на следующем рисунке, TransactionScope должен полностью окружать как сеанс, так и транзакцию NHibernate. Вызов TransactionScope.Complete () должен произойти после удаления сеанса. Любой другой порядок, скорее всего, приведет к неприятным сбоям в работе, таким как утечки соединения.

Мое мнение такжечто он должен работать с TransactionScope вместе, но это не так, ни в 3.3.xx, ни в версии 4.0.0.400.

Приведенный выше рецепт может работать, но нужно протестировать его с вложенным TrancactionScope, с внутренним TransactionScope, которыйопределен Transaction.Suppress (при использовании SQL) и т.д ...

0 голосов
/ 08 декабря 2010

Один вопрос, почему вы выполняете внутреннюю сессию.BeginTransaction - начиная с версии 2.1 GA NHibernate автоматически регистрируется в контекстах TransactionScope, поэтому больше нет причин делать свою собственную.

...