Предотвращение каскадного обновления отношений «многие ко многим» с помощью NHibernate / FluentNHibernate, - PullRequest
0 голосов
/ 19 апреля 2011

У меня есть простые отношения многие ко многим между классом User и классом Place.Это отношение представлено свойством «Соседство» пользователя

public class User
{
  public virtual IList<UserPlace> Neighbourhood { get; set; }
}

Класс UserPlace - это просто компонент, который добавляет один фрагмент информации к отношениям между пользователем и местом:

public class UserPlace
{
  public virtual User User { get; set; }
  public virtual Place Place { get; set; }
  public virtual bool IsDefault { get; set; }
}

Соотношение отображается следующим образом:

public class UserMappings : ClassMap<User>
{
  //... other mappings

  HasMany(x => x.NeighbourHood)
            .Component(c =>
                           {
                               c.Map(x => x.IsDefault);
                               c.References(x => x.Place).Cascade.None();
                           }
            ).Not.LazyLoad().Cascade.SaveUpdate();
}

Когда создается пользователь, из базы данных загружается и добавляется несколько мест, причем для одного из них установлено значение по умолчанию.Когда пользователь сохраняется, связанные сущности UserPlace также сохраняются.

Проблема, с которой я сталкиваюсь, заключается в том, что каждая сущность Place , связанная с UserPlace, также обновляется.Это нежелательный эффект, и я пытался не допустить, чтобы Cascade to Place состоялся (каламбур не предназначен), установив для Cascade значение None () ... однако это ничего не меняет.

Iудалось остановить это обновление, указав, что не следует обновлять каждое свойство в Place ([PropertyName] .Not.Updated ()).Это работает, но это не решение.

У кого-нибудь есть какие-либо идеи о том, как я могу предотвратить это?

Редактировать : Отображение объекта Place имеет DynamicUpdate (), также сущность не должна изменяться при сохранении пользователя.

PS!Я не думаю, что это имеет значение для этого сценария (но я могу ошибаться!), Но учтите это также: сущности Place загружаются вне NHibernate (используя ADO.NET и хранимую процедуру,из-за некоторых геопространственных запросов, которые я не мог сделать с помощью NHibernate), а затем подключил к сеансу, вызвав Session.Update () для каждого объекта.

1 Ответ

1 голос
/ 19 апреля 2011

Это не каскадная проблема.NH обновляет места, потому что вы звоните session.Update с каждого места.То, что вы пишете в PS, абсолютно связано с проблемой.

Когда вы вызываете update для отдельного объекта, NH не может знать, действительно ли состояние объекта изменилось или нет.Чтобы избежать запроса данных перед обновлением (два обхода базы данных), он обновляет данные вслепую.

Чтобы избежать этого:

  • Установить выбор до обновления (SelectBeforeUpdate в совершенстве)
  • Использование session.Merge(place).Он также выполняет запрос перед обновлением.Обратите внимание, что у него есть возвращаемое значение, которое необходимо использовать.
  • Используйте session.Load(place.Id), чтобы создать прокси для рассматриваемого места и назначить его (обратите внимание, что NH снова загружает место при доступе к свойствам прокси)
  • Используйте session.Lock(place, LockMode.None) для помещения объектов в сеанс.
  • Используйте запрос NH для получения мест.
...