Могу ли я использовать AdoNetTransactionFactory NHibernate с распределенными транзакциями?

Я имею дело со странной проблемой, связанной с NHibernate и распределенными транзакциями в службе WCF. См. Взаимоблокировки, вызывающие "Серверу не удалось возобновить транзакцию" с NHibernate и распределенные транзакции для более подробной информации.

Одна вещь, которая, кажется, решает мою проблему, - это использование AdoNetTransactionFactory NHibernate вместо AdoNetWithDistributedTransactionsFactory.

Я считаю, что AdoNetWithDistributedTransactionsFactory участвует в правильной работе механизма кэширования второго уровня NHibernate, но мы его не используем. Какие еще проблемы (если есть) существуют при использовании AdoNetTransactionFactory с распределенными транзакциями?

Спасибо за ваше время!


person jon without an h    schedule 20.12.2011    source источник


Ответы (3)


Я заметил, что вы упомянули из своего другого вопроса/ответа:

SqlConnection class is not thread-safe, and that includes closing the connection 
on a separate thread. Based on this response we have filed a 
bug report for NHibernate.

Однако из документации NHibernate:

11.2. Threads and connections

При создании сеансов NHibernate следует соблюдать следующие правила:

  • Never create more than one concurrent ISession or ITransaction instance per database connection.

  • Be extremely careful when creating more than one ISession per database per transaction. The ISession itself keeps track of updates made to loaded objects, so a different ISession might see stale data.

  • The ISession is not threadsafe! Never access the same ISession in two concurrent threads. An ISession is usually only a single unit-of-work!

    Если вы пытаетесь установить многопоточное соединение с NHibernate, возможно, оно просто не сработает. Рассматривали ли вы другой ORM, например Entity Framework?

    Независимо от того, какой ORM вы выберете, соединение с базой данных не будет потокобезопасным. Это универсально.

    «Многие драйверы БД не являются потокобезопасными. Использование синглтона означает, что если у вас много потоков, все они будут использовать одно и то же соединение. Шаблон синглтона не дает вам потокобезопасности. Он просто позволяет многим потокам легко совместно использовать «глобальный» пример." - https://stackoverflow.com/a/6507820/1026459

    person Travis J    schedule 24.09.2012
    comment
    Трэвис, мы следовали всем рекомендациям NH по многопоточности. Проблема была внутри самого NH — если распределенная транзакция была прервана сервером БД, NH закроет соединение в другом потоке. - person jon without an h; 01.10.2012

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

    • ConnectionReleaseMode.AfterTransaction не будет соблюден. Вместо этого NHibernate будет освобождать соединение после каждого оператора и, таким образом, повторно получать соединение из пула для следующего. В зависимости от вашего поставщика данных это может вызвать эскалацию транзакции до распределенной.
    • FlushMode.Commit не будет соблюден. Вместо этого потребуются явные сбросы. (Auto сбрасывается до того, как запросы все еще могут возникать.)
    • Работы, которые необходимо изолировать от текущей системной транзакции, все равно будут включены в нее. (Если свойство строки подключения Enlist не равно false.) Такие работы могут включать запросы генераторов идентификаторов, такие как получение следующего старшего значения для генератора таблицы hilo. Если транзакция будет отменена, NHibernate может использовать конфликтующие идентификаторы.
    • Сеанс NHibernate не сможет правильно отслеживать блокировки, которые он удерживает на сущностях. Считая себя вне транзакции, он будет считать, что не имеет на них блокировки. Таким образом, он может попытаться (например, по запросу пользовательского кода) повторно заблокировать их с более низким уровнем блокировки, чем тот, который транзакция уже удерживает для них в базе данных. Не уверен, к какому результату это может привести. (В лучшем случае игнорируется, в худшем...)
    • Кэш второго уровня будет отключен, как только вы начнете изменять данные. NHibernate сортирует "недействительные" записи кэша в такой ситуации и повторно активирует их только после завершения транзакции с обновлением. Но поскольку он не будет знать о транзакциях...
    • Некоторые расширения (возможно, Envers) могут полагаться на события транзакций NHibernate и больше не будут работать должным образом.
    person Frédéric    schedule 29.06.2017

    Я настоятельно рекомендую обновиться до nhibernate 3.2 (или версии, близкой к ней). Почему? Начиная с версии 2.1, в AdoNetWithDistributedTransactionFactory были внесены значительные улучшения (читай — переписаны). На самом деле, теперь он правильно обрабатывает TransactionScopes/ambient-transactions и тому подобное. Когда мы запустили 2.1 в продакшн, мы столкнулись со многими проблемами, связанными с распределенными транзакциями. Нам пришлось самостоятельно исправлять массу вещей и перекомпилировать NHibernate. 3.2, похоже, исправили многие проблемы, связанные с этой темой.

    У меня нет источника рядом со мной, но, если мне не изменяет память, AdoNetTransactionFactory не проверяет/обрабатывает внешние транзакции. Таким образом, вы сталкиваетесь с загрузочными транзакциями NHibernate, когда они отсутствуют в сеансе (с помощью ISession.BeginTransaction()).

    person Newbie    schedule 25.12.2011
    comment
    Спасибо за ответ. Я предполагаю, что вы читали мой другой вопрос, где я упомянул, что мы используем NH2.1. На самом деле мы пытались обновиться до 3.2, и это не решило наши проблемы. - person jon without an h; 28.12.2011
    comment
    В ходе нашего тестирования мы обнаружили, что AdoNetTransactionFactory не знает о внешних транзакциях, но базовый SqlConnection по-прежнему участвует в нем, поэтому все работает, даже если мы не используем транзакцию NH. Я считаю, что AdoNetWithDistributedTransactionsFactory в основном участвует в обеспечении правильной работы механизма кэширования второго уровня NH, но я хотел бы знать, есть ли с ним какие-либо другие проблемы. - person jon without an h; 28.12.2011
    comment
    AdoNetWithDistributedTransactionFactory будет автоматически подключаться к внешней транзакции в большем количестве случаев и будет иногда работать без использования транзакции NHibernate. Хотя, к сожалению, даже в 3.3 есть некоторые проблемы, поэтому по-прежнему рекомендуется всегда использовать транзакцию NHibernate в дополнение к TransactionScope. Я боюсь, что с текущим подходом могут возникнуть некоторые проблемы, которые по своей сути невозможно исправить из-за ограничений в System.Transactions и System.Data. - person Oskar Berggren; 20.09.2012