NHibernate: удаление из коллекции против ассоциации и каскадных стилей - PullRequest
3 голосов
/ 27 октября 2011

У меня проблемы с пониманием того, как NHibernate знает что-либо об объектах, удаленных из ассоциации (и затем выполняет каскадный стиль, такой как delete-orphant).Я имею в виду, что на уровне базы данных, если бы я хотел удалить ассоциацию, мне пришлось бы физически войти в систему и удалить некоторые FK.Как это происходит в мире NH?Должен ли я переназначить свои классы, удалить ранее установленные родительские / дочерние ассоциации (отношения), NH выполняет сравнительный анализ, выясняет, что что-то было изменено, и затем предпринимает соответствующие действия?В этом посте Айенде говорит о различных стилях каскадирования, а delete-orphat описывается как «... Кроме того, когда объект удаляется из ассоциации и не ассоциируется с другим объектом (осиротевшим), такжеудалить его ... "Как происходит это удаление?

1 Ответ

5 голосов
/ 28 октября 2011

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

Вот почему вы всегда должны объявлять свойства коллекции с помощью интерфейсов (IList, ISet и т. Д.) И никогда не заменять свойство коллекции на объекте, который был загружен с помощью NHibernate.

Дополнительная информация запрашивается в комментариях:

Есть полезное обсуждение Фабио Мауло (ведущего разработчика NHibernate) по отображению коллекций здесь , которое я настоятельно рекомендую прочитать. Но чтобы попытаться дать краткий ответ на ваши вопросы:

Но как NH узнает, что связь между объектами была удалена?

Обычно, работая в модели ОО с многими ассоциациями, мы управляем отношениями у родителя. То есть ребенок считается связанным с родителем, когда он находится в коллекции родителя. Э.Г.

child.Parent = parent;
parent.Children.Add(child);  // This is the critical bit 
session.Save(parent);        // to have an INSERT generated here

Аналогичным образом удаление элемента из коллекции нарушает связь (при условии использования правильных атрибутов сопоставления)

child.Parent = null;
parent.Children.Remove(child);  // This is critical bit
session.Save(parent);           // To have DELETE or UPDATE statement generated depending on cascade settings.

Это противоположно тому, как все работает в реляционном мире, где мы управляем отношениями у ребенка с помощью внешнего ключа в дочернем ряду.

Для более детального понимания нет ничего лучше, чем загрузить исходный код NHibernate, создать простой тестовый пример и затем перейти в отладчик.

В чем причина "Вот почему ..."

Есть ряд вещей, которыми NHibernate занимается при управлении коллекциями ассоциаций. Он делает это, используя свои собственные классы коллекции, которые отслеживают, являются ли они грязными, в каком состоянии они находились, когда они были загружены из БД, и рядом других интересных вещей. Если вы замените эти объекты, NHibernate потеряет эту возможность. Так, например, если вы хотите избавиться от всех элементов в коллекции, вы должны сделать:

parent.Children.Clear(); // The collection object is preserved and NHibernate knows you want them all deleted.

Вы никогда не должны делать:

parent.Children = new List<X>(); // NHibernate will not track changes to this collection.

Для дальнейшего чтения вы также можете взглянуть на this .

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