NHibernate ISession Флеш:Где и когда его использовать и почему?

StackOverflow https://stackoverflow.com/questions/43320

Вопрос

Одна из вещей, которая меня совершенно сбивает с толку, - это использование session.Flush, в сочетании с session.Commit, и session.Close.

Иногда session.Close работает, например, он фиксирует все изменения, которые мне нужны.Я знаю, что мне нужно использовать фиксацию, когда у меня есть транзакция или единица работы с несколькими созданиями / обновлениями / удалениями, чтобы я мог выбрать откат в случае возникновения ошибки.

Но иногда я действительно захожу в тупик из-за логики, стоящей за этим session.Flush.Я видел примеры, когда у вас есть session.SaveOrUpdate() за этим следует промывка, но когда я удаляю промывку, она все равно работает нормально.Иногда я сталкиваюсь с ошибками в операторе Flush, говорящими о том, что время ожидания сеанса истекло, и, удалив его, я убедился, что я не столкнулся с этой ошибкой.

Есть ли у кого-нибудь хорошие рекомендации относительно того, где и когда использовать Флеш?Я просмотрел документацию NHibernate для этого, но я все еще не могу найти прямого ответа.

Это было полезно?

Решение

Кратко:

  1. Всегда используйте транзакции
  2. Не используйте Close(), вместо этого переносите свои вызовы на ISession внутри using заявление или управляйте жизненным циклом вашей ISession где-нибудь в другом месте.

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

Время от времени ISession выполнит инструкции SQL, необходимые для синхронизации состояния соединения ADO.NET с состоянием объектов, хранящихся в памяти.Этот процесс, flush, выполняется по умолчанию в следующих точках

  • из некоторых призывов Find() или Enumerable()
  • От NHibernate.ITransaction.Commit()
  • От ISession.Flush()

Инструкции SQL выдаются в следующем порядке

  1. все вставки объектов выполняются в том же порядке, в каком соответствующие объекты были сохранены с использованием ISession.Save()
  2. все обновления объекта
  3. все удаления коллекции
  4. все удаления, обновления и вставки элементов коллекции
  5. все вставки коллекции
  6. все удаления объектов выполняются в том же порядке, в каком были удалены соответствующие объекты с помощью ISession.Delete()

(Исключением является то, что объекты, использующие генерацию собственных идентификаторов, вставляются при их сохранении.)

За исключением тех случаев, когда вы объясняете Flush(), нет абсолютно никаких гарантий относительно того, когда сеанс выполняет ADO.NET вызовы, только порядок, в котором они выполняются.Однако NHibernate гарантирует, что ISession.Find(..) методы никогда не вернут устаревшие данные;они также не вернут неверные данные.

Можно изменить поведение по умолчанию, чтобы сброс выполнялся реже.Тот Самый FlushMode класс определяет три различных режима:сбрасывать только во время фиксации (и только тогда, когда NHibernate ITransaction Используется API), промывать автоматически, используя описанную процедуру, или никогда не промывать, если Flush() вызывается явно.Последний режим полезен для длительных этапов работы, когда ISession остается открытым и отключенным в течение длительного времени.

...

Также обратитесь к этот раздел:

Завершение сеанса включает в себя четыре различных этапа:

  • очистите сеанс
  • зафиксируйте транзакцию
  • закройте сеанс
  • обрабатывать исключения

Очистка сеанса

Если вы случайно используете ITransaction API, вам не нужно беспокоиться об этом шаге.Это будет выполнено неявно, когда транзакция будет зафиксирована.В противном случае вам следует позвонить 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() call выполнит любую необходимую промывку.Если по какой-то причине вы не используете транзакции 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, сохраняю объект, затем удаляю, затем отключаю identity insert.Без этой очистки казалось, что он включает и выключает вставку идентификатора, а затем сохраняет объект.

Использование Flush() дало мне больше контроля над происходящим.

Вот еще один пример:

Отправка сообщения NServiceBus внутри TransactionScope

Я не совсем понимаю, почему в этом случае, но функция Flush() предотвратила возникновение моей ошибки.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top