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 .