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

У меня есть простая связь «многие ко многим» между классом 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 () ... но это ничего не меняет.

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

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

Изменить: для сопоставления объекта "Место" также задана функция DynamicUpdate (), поэтому объект не должен изменяться при сохранении пользователя.

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


person Øyvind    schedule 19.04.2011    source источник


Ответы (1)


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

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

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

  • Установите выбор перед обновлением (SelectBeforeUpdate свободно)
  • Используйте session.Merge(place). Он также выполняет запрос перед обновлением. Обратите внимание, что у него есть возвращаемое значение, которое необходимо использовать.
  • Используйте session.Load(place.Id), чтобы создать прокси для рассматриваемого места и назначить его (обратите внимание, что NH снова загружает место при доступе к свойствам прокси)
  • Используйте session.Lock(place, LockMode.None), чтобы поместить объекты в сеанс.
  • Используйте запрос NH для получения мест.
person Stefan Steinegger    schedule 19.04.2011
comment
Привет, Стефан, это блестящий ответ. Спасибо. У меня было ощущение, что это не каскадная проблема (я продолжал читать об этом после публикации здесь), и теперь вы дали мне больше ясности в том, что здесь происходит. Я решил проблему, загрузив свои объекты Place через NHibernate после нахождения их идентификаторов другими способами. Это немного взломано, но на данный момент у меня нет способа NHibernate-y для выполнения моего пространственного запроса. Еще раз спасибо. - person Øyvind; 19.04.2011