Подтвердить что ты не робот

NHibernate Flush - как это работает?

Я немного смущен тем, как работает FlushNHibernate.ISession) в NHibernate.

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

Однако при обновлении и объекте с использованием ISession.SaveOrUpdate(entity) или ISession.Update(entity) объект в базе данных не обновляется --- мне нужно вызвать ISession.Flush, чтобы его обновить.

Процедура обновления объекта следующая:

  • Получить объект из базы данных с помощью ISession.Get(typeof(T), id)
  • Измените свойство объекта, например myCar.Color="Green"
  • Верните его в базу данных с помощью ISession.Update(myCar)

myCar не обновляется в базе данных. Однако, если я затем назову ISession.Flush, то он будет обновлен.

Когда использовать Flush и когда не использовать его?

4b9b3361

Ответ 1

Во многих случаях вам не нужно заботиться о том, как сбрасывается NHibernate.

Вам нужно только сбросить флажок, если вы создали свое собственное подключение, потому что NHibernate не знает, когда вы его совершаете.

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

NHibernate flushes, если

  • вы вызываете commit
  • перед запросами, чтобы убедиться, что вы фильтруете фактическое состояние в памяти
  • когда вы вызываете флеш

Пример:

using (session = factory.CreateSession())
using (session.BeginTransaction())
{
  var entity = session.Get<Entity>(2);
  entity.Name = "new name";

  // there is no update. NHibernate flushes the changes.

  session.Transaction.Commit();
  session.Close();
}

Объект обновляется при фиксации. NHibernate видит, что ваш сеанс грязный и сбрасывает изменения в базу данных. Вам необходимо обновить и сохранить, только если вы внесли изменения вне сеанса. (Это означает, что это отдельный объект, который не известен сеансу).


Заметки о производительности: Flush не только выполняет необходимые инструкции SQL для обновления базы данных. Он также ищет изменения в памяти. Поскольку в POCOs нет грязного флага, ему необходимо сравнить каждое свойство каждого объекта в сеансе с кешем первого уровня. Это может стать проблемой производительности, когда это делается слишком часто. Есть несколько вещей, которые вы можете сделать, чтобы избежать проблем с производительностью:

  • Не зачищайте петли
  • Избегайте сериализованных объектов (для проверки изменений требуется сериализация)
  • Используйте объекты только для чтения, если это необходимо
  • Установите mutable = false, если это необходимо
  • При использовании пользовательских типов в свойствах реализуйте эффективные методы Equals
  • Осторожно отключите автозагрузку, когда вы уверены, что знаете, что делаете.

Ответ 2

NHibernate будет выполнять команды SQL только тогда, когда это необходимо. Он отложит выполнение операторов SQL как можно дольше.

Например, когда вы сохраняете объект с присвоенным идентификатором, он скорее всего отложит выполнение инструкции INSERT. Однако, когда вы вставляете объект, у которого есть идентификатор автоинкремента, например, NHibernate необходимо ВСТАВИТЬ объект напрямую, поскольку он должен знать идентификатор, который будет назначен этому объекту.

Когда вы явно вызываете flush, NHibernate будет выполнять инструкции SQL, необходимые для объектов, которые были изменены/созданы/удалены в этом сеансе.

Flush