Транзакции NHibernate при чтении - PullRequest
32 голосов
/ 01 ноября 2009

Я прочитал документацию и объяснение того, почему настоятельно рекомендуется использовать транзакции для операций чтения в NH. Тем не менее, я до сих пор еще не полностью «купил» его. Может ли кто-нибудь попытаться объяснить это, не сказав мне RTFM, что я уже сделал? ;)

Ответы [ 5 ]

24 голосов
/ 01 ноября 2009

Это сообщение от одного из авторов может иметь ваш ответ:

Даже если мы только читаем данные, мы хочу использовать транзакцию, потому что используя транзакцию, убедитесь, что мы получаем последовательный результат из базы данных. NHibernate предполагают, что все доступ к база данных сделана под сделка, и сильно отговаривать любое использование сеанса без сделка.

Оставляя в стороне вопрос безопасности работа с транзакциями, Предположение, что транзакции дорого, и мы должны оптимизировать их ложный. Как уже упоминалось, базы данных всегда работают в сделка. И базы данных были сильно оптимизирован для работы с сделки. Вопрос в том, что это за утверждение или за партию. Есть некоторый объем работы, который нужно должно быть сделано, чтобы создать и распоряжаться сделка, и необходимость сделать это за заявление на самом деле дороже, чем делать это за партию.

8 голосов
/ 01 ноября 2009

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

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

Это, конечно, верно для ЛЮБОГО уровня доступа к данным, который неявно запускает транзакции для вас, если вы этого не делаете. Это не ограничивается NHibernate.

6 голосов
/ 01 ноября 2009
var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);

Что если какая-то другая транзакция удалит строки из Bar между двумя запросами? У вас будут проблемы с фантомными данными. Это не специфическая проблема NHibernate. У вас будет такая же проблема с любым другим видом доступа к базе данных без использования транзакций. Вам следует прочитать руководство по транзакциям в целом, а не руководство NHiberante.

5 голосов
/ 01 ноября 2009

Давайте сосредоточимся на том, что произойдет, если вы не будете использовать транзакции. Обычно, но не обязательно, закрывать сеанс в конце обработки, но до того, как вы начнете читать данные (т. Е. Представление). Этот метод распространяется под термином « Open Session in View » (хотя он, очевидно, имеет шаблон для предотвращения чтения перед закрытием). Этот шаблон часто используется в веб-приложении, где сеанс открывается, когда запрос поступает и закрывается непосредственно перед записью в поток ответов.

(N) Hibernate нужен сеанс и транзакция. Когда вы читаете без использования явной транзакции, транзакция будет настроена для вас. Когда вы читаете после фиксации транзакции, поведение зависит от конфигурации NH и драйвера.

И ODBC, и JDBC не определяют, что происходит, когда соединение закрыто, и есть незафиксированные или неподтвержденные данные. Когда соединение открывается, возможно, новая транзакция запускается автоматически.

Использование нетранзакционного доступа может использоваться только вместе с установкой auto-commit явно в конфигурации NHibernate. Если нет, используется драйвер по умолчанию, и он может работать или не работать.

Короче говоря, есть много недостатков и неопределенного поведения, когда вы не используете транзакции при чтении. Это будет работать часто, но это зависит от конфигурации, применяемых шаблонов, драйверов. Существует большая вероятность, что вы получите LazyInitializationException s, что является обычным результатом чтения после принятия без открытия новой транзакции.

«Лучшая практика» - использовать одну транзакцию для чтения / записи, а другую - только для чтения. Это кратко описано в предыдущей ссылке, раздел «Могу ли я использовать две транзакции в сеансе», но требует большей реализации.

Это не только «использовать транзакции для чтения», но и «использовать ту же транзакцию, которую вы используете для записи для чтения». (а затем, хотя это и так, фактическое приложение будет зависеть от ваших текущих шаблонов, количества уровней, кэширования и конфигурации).

Обновление: немного расширено, устранены некоторые неопределенности

3 голосов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...