Ответ 1
Коротко:
- Всегда использовать транзакции
- Не используйте
Close()
, вместо этого переносите свои вызовы наISession
внутри оператораusing
или управлять жизненным циклом вашего ISession где-то еще.
Из документация:
Время от времени
ISession
будет выполнять инструкции SQL, необходимые для синхронизации состояния соединения ADO.NET с состоянием объектов, хранящихся в памяти. Этот процесс, заподлицо, происходит по умолчанию в следующих точках
- из некоторых вызовов
Find()
илиEnumerable()
- от
NHibernate.ITransaction.Commit()
- from
ISession.Flush()
Операторы SQL выдаются в следующем порядке
- все вставки объектов, в том же порядке соответствующие объекты были сохранены с помощью
ISession.Save()
- все обновления сущностей
- удаление всех коллекций
- удаление, обновление и вставка элементов коллекции
- все вставки коллекции
- все удаления сущностей, в том же порядке соответствующие объекты были удалены с помощью
ISession.Delete()
(Исключением является то, что объекты, использующие встроенную идентификацию, вставляются, когда они сохраняются.)
За исключением случаев, когда вы объясняете
Flush()
, нет никаких гарантий относительно того, когда сеанс выполняет вызовы ADO.NET, а только тот порядок, в котором они выполняются. Однако NHibernate гарантирует, что методыISession.Find(..)
никогда не возвратят устаревшие данные; и они не вернут неверные данные.Можно изменить поведение по умолчанию, так что сброс происходит реже. Класс
FlushMode
определяет три разных режима: только очистка во время фиксации (и только при использовании API NHibernateITransaction
), автоматически сбрасывается автоматически с помощью объясняемой процедуры или никогда не сбрасывается, если толькоFlush()
не вызывается явно. Последний режим полезен для длительных периодов работы, гдеISession
остается открытым и отключается в течение длительного времени.
...
Также см. этот раздел:
Завершение сеанса включает в себя четыре различные фазы:
- очистить сеанс
- совершить транзакцию
- закрыть сеанс
- исключение дескрипторов
Очистка сеанса
Если вы используете API
ITransaction
, вам не нужно беспокоиться об этом шаге. Это будет выполняться неявно при совершении транзакции. В противном случае вы должны позвонитьISession.Flush()
, чтобы все изменения были синхронизированы с базой данных.Выполнение транзакции базы данных
Если вы используете API-интерфейс NHibernate ITransaction, это выглядит так:
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()
возвращает его в пул.