NHibernate Flush - Как это работает? - PullRequest
20 голосов
/ 23 апреля 2009

Я немного растерялся из-за того, как FlushNHibernate.ISession) в NHibernate работает.

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

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

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

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

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

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

Ответы [ 2 ]

28 голосов
/ 23 апреля 2009

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

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

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

NHibernate сбрасывает, если

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

Пример:

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 для обновления базы данных. Он также ищет изменения в памяти. Поскольку в POCO нет грязного флага, необходимо сравнить каждое свойство каждого объекта в сеансе с его кэшем первого уровня. Это может стать проблемой производительности, когда это делается слишком часто. Есть несколько вещей, которые вы можете сделать, чтобы избежать проблем с производительностью:

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

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

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

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

Flush

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