Свободный каскад NHibernate один ко многим Удалить - PullRequest
4 голосов
/ 12 марта 2012

Я много видел эту проблему, но ни одно из решений не помогло мне.

У меня есть отношение один-ко-многим в C #, сопоставленное с MS SQL с помощью свободного NHibernate. Когда я пытаюсь удалить дочерний элемент, NHibernate пытается это сделать, задав для внешнего ключа значение NULL, что, конечно, приводит к ошибке.

Решения для подобных вопросов заключались в добавлении Inverse к HasMany отображению родителя. Однако сейчас возникает эта проблема:

var parent = //something
parent.Children.Clear();
session.Update(parent);

Это приводит к удалению всего родителя! Почему?

1 Ответ

11 голосов
/ 13 марта 2012

Использование «Inverse» в отображении меняет представление о том, кто «владеет» отношениями между родителем и ребенком. Указывая «Inverse», NH в основном действует так, как если бы дочерняя сторона отношений решала, принадлежит ли она родителю, а не родительская, решая, есть ли у нее дочерний элемент. Хороший пример из реальной жизни - студенты, поступающие в колледж. Студент может решить больше не принадлежать к колледжу, и все же может существовать и быть значимым как сущность. Кроме того, именно студент, а не колледж, решает, следует ли сформировать или разорвать эти отношения с колледжем (в реальной жизни да, существуют ситуации, когда колледж говорит, что студент больше не приветствуется, но колледж не просто говорит студенту с хорошей репутацией «ты бросаешь», это студент говорит колледжу, что).

Суть в том, что, определяя отношения между Родителем и Детьми как Обратные, NH рассматривает «одну» сторону отношения (Родителя) как сторону, которая не может существовать вне контекста отношений. Итак, когда вы очищаете всех детей, родитель, у которого теперь нет детей, становится «сиротой», а NH удаляет его.

Это не похоже на то, что вы хотите; поэтому я бы удалил обратное сопоставление из этого отношения, позволяя Родителю «владеть» этим отношением со своими детьми. Удалите всех детей, и они станут осиротевшими и удалены, но Родитель все еще рядом. Теперь у вас есть проблема, что Дети не могут быть «осиротевшими», потому что внешний ключ не может быть обнуляемым; они должны принадлежать чему-то. NH требует, чтобы FK дочерних записей обнулялся, если вы собираетесь использовать каскадные правила «удаления-сироты». Это связано с тем, что удаленное удаление является двухпроходной операцией, которая требует, чтобы запись была сначала потерянной, установив для ее поля FK значение null. Затем NH выполнит вторую инструкцию, чтобы удалить из таблицы любую запись с пустым FK. Таким образом, даже с обнуляемым полем FK, используя NH с желаемыми каскадными правилами, вы не будете иметь никаких записей с нулевым FK в течение более чем переходного периода.

Если это неприемлемо, вам придется удалить потерянное удаление из правил каскадирования и вручную удалить каждую запись, а также удалить ее из сеанса.

foreach(var child in parent.Children)
      session.Delete(child);

   parent.Children.Clear();
   session.Update(parent);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...