#nhibernate
#nhibernate
Вопрос:
Мне трудно понять, как NHibernate знает что-либо об объектах, удаленных из ассоциации (а затем выполняет каскадный стиль, такой как delete-orphant). Я имею в виду, что на уровне базы данных, если бы я хотел удалить ассоциацию, мне пришлось бы физически войти в систему и удалить некоторый FK. Как это происходит в мире NH? Переназначаю ли я свои классы, удаляю ранее установленную родительскую / дочернюю ассоциацию (отношения), NH проводит сравнительный анализ, выясняет, что что-то было изменено, а затем предпринимает соответствующие действия? В этом посте Айенде рассказывает о разных каскадных стилях, а удаление-orphat описывается как «… В дополнение к этому, когда объект удаляется из ассоциации и не связан с другим объектом (потерянным), также удалите его … » Как происходит это удаление?
Ответ №1:
NHibernate просматривает все сопоставленные коллекции, сопоставленные, которые принадлежат объектам в сеансе NHibernate. По мере внесения изменений (добавления / удаления) NHibernate помечает их как грязные. Когда приходит время для удаления изменений, он сравнивает элементы в грязных коллекциях и может определить, какие элементы были добавлены и удалены. В зависимости от параметров каскада для коллекции NHibernate может затем сохранить эти изменения в базе данных.
Вот почему вы всегда должны объявлять свойства коллекции с помощью интерфейсов (IList, ISet и т. Д.) И Никогда не заменять свойство коллекции на объект, который был загружен с помощью NHibernate.
Дополнительная информация запрошена в комментариях:
Здесь есть полезное обсуждение Фабио Мауло (ведущего разработчика NHibernate) сопоставления коллекций, которое я настоятельно рекомендовал бы прочитать. Но чтобы попытаться дать краткий ответ на ваши вопросы:
Но как NH узнает, что связь между объектами была удалена?
Обычно при работе в модели OO со многими ассоциациями мы управляем отношениями у родительского элемента. То есть дочерний элемент считается связанным с родительским элементом, когда он находится в родительской коллекции. Например.
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.
Для дальнейшего чтения вы также можете взглянуть на это.
Комментарии:
1. Ваше объяснение в первом абзаце имеет смысл, когда дело доходит до добавления / удаления элементов из коллекций. Но как NH узнает, что связь между объектами была удалена? Вы также сказали, что «Вот почему вы всегда должны объявлять свойства коллекции с помощью интерфейсов …» В чем причина «Вот почему …» Это потому, что элементы помечены как грязные, или ключевым моментом здесь является постоянство в базе данных?