Nhibernate один ко многим удалить не работает

Привет, у меня есть один ко многим ComplianceSet -> ComplianceItem. ComplianceItem имеет один ко многим ComplianceItem -> ComplianceItemInstance.

у меня есть

набор соответствия

HasMany(x => x.GetUserComplianceItems()).Inverse().Access.CamelCaseField(Prefix.Underscore).LazyLoad().Cascade.AllDeleteOrphan();

И

пункт соответствия

HasMany(x => x.GetUserComplianceItemInstances()).Inverse().Access.CamelCaseField(Prefix.Underscore).LazyLoad().Cascade.AllDeleteOrphan();

Тогда в моем коде у меня есть

userComplianceSet.GetUserComplianceItems().FirstOrDefault(....); ... userComplianceItem.RemoveUserComplianceItemInstance(userComplianceItemInstance);

этот код возвращает

удаленный объект будет повторно сохранен каскадно (удалить удаленный объект из ассоциаций)[DecisionCritical.Core.Domain.UserComplianceSet#12]

Теперь это очень расстраивает. Если я удалю каскад из обеих коллекций, код вернет успех, но БД покажет, что он ничего не сделал. поле ComplianceItemInstance.ComplianceItemId по-прежнему заполнено, и, конечно, элемент все еще существует. В любом случае, я просто хочу иметь возможность удалить дочерний элемент из коллекции, вызвать save для объекта, содержащего коллекцию, и избавиться от этой чертовой штуки. Я пробовал всевозможные перестановки каскада, сохранения (сохранения набора, сохранения элемента), добавления удаления в ComplianceItemInstance и т. д. и не могу заставить это работать.

Пожалуйста помоги


person Raif    schedule 18.04.2011    source источник
comment
Каков код RemoveUserComplianceItemInstance?   -  person Ilya Kogan    schedule 20.04.2011
comment
Итак, я понял, в чем проблема, и я думаю, что Илья собирался указать мне в этом направлении. поскольку это двунаправленное отношение, я должен установить UserComplianceItemInstance.UserComplianceItem = null перед сохранением родителя.   -  person Raif    schedule 20.04.2011
comment
Теперь я пробовал всевозможные вещи, одна из которых заключалась в том, чтобы сделать ее однонаправленной ссылкой, однако (и я не знал этого в то время), если для fk установлено значение не null в таблице db, однонаправленная ссылка не будет работать потому что он сохраняет дочерний элемент с нулевым fk, а затем обновляет дочерний элемент с fk. Я получал ошибку «не могу вставить ноль в fk» и предполагал, что я на неправильном пути. Во всяком случае, теперь все лучше. хоть и на пару дней жизни меньше. Могу ли я поставить плюс один за выяснение моего собственного ответа? :)   -  person Raif    schedule 20.04.2011
comment
да, вы можете ответить на свой вопрос и выбрать свой ответ как принятый, и это даже поощряется. См. здесь: meta.stackexchange.com /questions/17845/ и здесь: meta.stackexchange.com/questions/12513/ и здесь: meta.stackexchange.com/questions/17463/   -  person Ilya Kogan    schedule 21.04.2011


Ответы (1)


Я боролся с тем же самым. Реакция немного запоздала, но, возможно, будущие читатели смогут извлечь из этого пользу.

Решение, разрешающее null в качестве внешнего ключа для дочерней таблицы, работает, но может быть нежелательным с точки зрения проектирования базы данных, если ваш дочерний элемент все равно не может существовать без родителя. Я не предпочитаю изменять дизайн базы данных только потому, что этого требует NHibernate. Также переход с двунаправленного на однонаправленный был для меня нежелательным. Поэтому я углубился и попробовал всевозможные комбинации отображений.

Я обнаружил, что использование inverse = true решило проблему. Сначала я подумал, что это плохое поведение со стороны NHibernate, поскольку inverse = true в основном объясняется тем, что дочерняя коллекция отвечает за отношение, которое, как я думал, я уже рассмотрел, вручную обновив дочернюю и родительскую. Но эта ответственность больше связана с базой данных, чем с чем-либо еще.

Используя inverse = true, по-прежнему можно удалить дочерний элемент, удалив его из родителя, если у вас есть Cascade.AllDeleteOrphan на родительской стороне сопоставления, все будет правильно обновлено. Если вы решите использовать Cascade.All, вы также должны явно удалить дочерний элемент.

Если родитель не загружен, вы также можете выбрать немедленное удаление дочернего элемента, просто удалив его в текущем сеансе. Но это не работает, если родитель загружен, и в этом случае возникнут проблемы с каскадным повторным сохранением.

Суть для меня в том, что инверсия работает. И я не нашел сценария, в котором inverse = false дает мне лучшие результаты, но я могу вернуться к этому мнению, когда углублюсь в NHibernate.

person Leroy    schedule 03.04.2012