NHibernate ISession Flush: где и когда его использовать, и почему?
одна из вещей, которые меня полностью смущают, - это использование session.Flush,совместно с session.Commit и session.Close.
иногда session.Close работает, например, он фиксирует все изменения, которые мне нужны. Я знаю, что мне нужно использовать commit, когда у меня есть транзакция или единица работы с несколькими созданиями/обновлениями/удалениями, чтобы я мог выбрать откат, если произойдет ошибка.
но иногда меня действительно загоняет в тупик логикаsession.Flush. Я видел примеры, когда вы есть session.SaveOrUpdate() затем следует флеш, но когда я удаляю флеш, он все равно работает нормально. Иногда я сталкиваюсь с ошибками в инструкции Flush, в которой говорится, что сеанс истек, и удаление его убедилось, что я не столкнулся с этой ошибкой.
есть ли у кого-нибудь хорошие рекомендации относительно того, где и когда использовать флеш? Я проверил документацию NHibernate для этого, но я все еще не могу найти простой ответ.
4 ответов:
кратко:
- всегда использовать операции
- не используйте
Close(), вместо этого оберните ваши звонки наISessionвнутриusingзаявление или управление жизненным циклом вашего ISession где-то еще.С документация:
времени
ISessionвыполнит инструкции SQL, необходимые для синхронизации ADO.NET состояние соединения с состоянием объектов держится в памяти. Этот процесс, flush, происходит по умолчанию в следующих точках
- от некоторых вызовов
Find()илиEnumerable()- С
NHibernate.ITransaction.Commit()- С
ISession.Flush()инструкции SQL выдаются в следующем порядке
- все вставки сущностей, в том же порядке соответствующие объекты были сохранены с помощью
ISession.Save()- все обновления лица
- все удаления коллекции
- все удаления, обновления и вставки элементов коллекции
- все коллекции вставки
- все удаления сущностей, в том же порядке соответствующие объекты были удалены с помощью
ISession.Delete()(исключение состоит в том, что объекты, использующие собственную генерацию идентификаторов, вставляются при их сохранении.)
кроме тех случаев, когда вы эксплицитность
Flush(), нет абсолютно никаких гарантий о том, когда сеанс выполняет ADO.NET звонки, только в том порядке, в котором они выполняются. Тем не менее, NHibernate гарантирует, чтоISession.Find(..)методы никогда не вернут устаревшие данные; и они не вернут неправильные данные.можно изменить поведение по умолчанию, чтобы сброс происходил реже. Элемент
FlushModeкласс определяет три различных режима: только флеш во время фиксации (и только когда NHibernateITransactionAPI используется), флеш автоматически с помощью объясненная процедура, или никогда не смывать, еслиFlush()вызывается явно. Последний режим полезен для длительно работающих единиц работы, гдеISessionостается открытым и отключенным в течение длительного времени....
Смотрите также в этом разделе:
завершение сеанса включает в себя четыре различных этапа:
- очистить сессии
- совершение сделки
- закрыть сессия
- обработка исключений
промывка сессии
если вы случайно используете
ITransactionAPI, вам не нужно беспокоиться об этом шаге. Он будет выполняться неявно при фиксации транзакции. В противном случае вы должны позвонитьISession.Flush()для обеспечения синхронизации всех изменений с базой данных.фиксация транзакции базы данных
если вы используете NHibernate ITRANSACTION API, это выглядит так:
tx.Commit(); // flush the session and commit the transactionесли вы управляете ADO.NET транзакции сами вы должны вручную
Commit()ADO.NET сделка.sess.Flush(); currentTransaction.Commit();если вы решили не фиксировать свои изменения:
tx.Rollback(); // rollback the transactionили:
currentTransaction.Rollback();если вы откатываете транзакцию, вы должны немедленно закрыть и отменить текущий сеанс, чтобы убедиться, что внутреннее состояние NHibernate согласовано.
закрытие ISession
вызов
ISession.Close()обозначает конец сеанса. Основное значение Close() заключается в том, что ADO.NET соединение будет прервано сеансом.tx.Commit(); sess.Close(); sess.Flush(); currentTransaction.Commit(); sess.Close();если вы предоставили свои связи,
Close()возвращает ссылку на него, так что вы можете вручную закрыть его или вернуть его в пул. В противном случаеClose()возвращает его в пул.
начиная с NHibernate 2.0, транзакции необходимы для операций с БД. Таким образом,
ITransaction.Commit()вызов будет обрабатывать любые необходимые промывки. Если по какой-то причине вы не используете транзакции NHibernate, то не будет автоматической промывки сеанса.
время от времени ISession будет выполнять инструкции SQL, необходимые для синхронизации ADO.NET состояние соединения с состоянием объектов, хранящихся в памяти.
и всегда использовать
using (var transaction = session.BeginTransaction()) { transaction.Commit(); }после того, как изменения будут зафиксированы, чем эти изменения, чтобы сохранить в базе данных мы используем транзакцию.Commit ();
вот два примера моего кода, где он потерпел бы неудачу без сеанса.Flush ():
http://www.lucidcoding.blogspot.co.uk/2012/05/changing-type-of-entity-persistence.html
в конце этого вы можете увидеть раздел кода, где я устанавливаю Identity insert on, сохраняю объект, затем сбрасываю, а затем устанавливаю Identity insert off. Без этого Флеша он, казалось, устанавливал Identity insert и выключал, а затем сохранял сущность.
польза притока() мне дали больше контроля над тем, что происходит.
вот еще один пример:
отправка сообщения NServiceBus внутри TransactionScope
Я не совсем понимаю, почему на этом, но Flush () предотвратил мою ошибку.
Comments