Могу ли я использовать AdoNetTransactionFactory от NHibernate с распределенными транзакциями? - PullRequest
7 голосов
/ 21 декабря 2011

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

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

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

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

Ответы [ 3 ]

1 голос
/ 25 сентября 2012

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

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 необходимо соблюдать следующие правила:

Никогда не создавайте более одного одновременного экземпляра ISession или ITransaction для соединения с базой данных.

Будьте предельно осторожны при создании более одного сеанса IS для каждой базы данных за транзакцию. Сам ISession отслеживает обновления, сделанные для загруженных объектов, поэтому другой ISession может видеть устаревшие данные.

ISession не является потокобезопасным! Никогда не обращайтесь к одной и той же сессии в двух параллельных потоках. ISession - это обычно только одна единица работы!

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

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

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

1 голос
/ 29 июня 2017

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

  • ConnectionReleaseMode.AfterTransaction не будет выполняться.Вместо этого NHibernate освобождает соединение после каждого оператора и, таким образом, повторно получает соединение из пула для следующего.В зависимости от вашего поставщика данных, это может вызвать эскалацию транзакции к распределенной.
  • FlushMode.Commit не будет выполняться.Вместо этого потребуются явные сбросы.(Auto сбрасывается до того, как запросы все еще могут возникать.)
  • Работы, требующие изоляции от текущей системной транзакции, все равно будут включены в нее.(Если только свойство строки подключения Enlist не равно false.) Такие работы могут включать запросы генераторов идентификаторов, такие как получение следующего высокого значения для генератора таблицы hilo.Если транзакция получает откат, NHibernate может затем использовать конфликтующие идентификаторы.
  • Сессия NHibernate не сможет правильно отследить блокировки, которые она удерживает на объектах.Считая себя вне транзакции, он будет считать, что не имеет на них блокировки.Таким образом, он может попытаться (по запросу кода пользователя в качестве примера) повторно заблокировать их с более низким уровнем блокировки, чем тот, который транзакция уже удерживает для них в базе данных.Не уверен, к какому результату это может привести.(В лучшем случае игнорируется, в худшем случае ...)
  • Кэш второго уровня будет отключен, как только вы начнете изменять данные.В такой ситуации NHibernate как бы «делает недействительными» записи в кеше и повторно активирует их только после завершения транзакции.Но поскольку он не будет знать о транзакциях ...
  • Некоторые расширения (возможно, Envers) могут полагаться на события транзакций NHibernate и больше не будут работать, как ожидалось.
0 голосов
/ 25 декабря 2011

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

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

...