我无法理解NHibernate如何知道从关联中删除的对象(然后执行像delete-orphant这样的级联样式)。我的意思是,在数据库级别,如果我想删除一个关联,我必须实际登录并删除一些FK。在NH世界中这是怎么发生的?我是否重新映射我的课程,删除以前建立的父/子关联(关系),NH做比较分析,挖掘某些事情已经改变然后采取适当的行动?在this post Ayende中讨论了不同的级联样式和删除 - 或者删除 - 或者描述为“......除此之外,当一个对象从被处理中删除而没有与另一个对象(孤立的对象)相关时,也删除它。 ..“这种移除是如何发生的?
答案 0 :(得分:5)
NHibernate监视NHibernate会话中对象所拥有的所有映射集合。当您进行更改(添加/删除)时,NHibernate将它们标记为脏。当需要刷新更改时,它会比较脏集合中的元素,并能够识别已添加和删除的项目。根据集合的级联选项,NHibernate可能会将这些更改持久保存到数据库中。
这就是为什么你应该总是使用接口(IList,ISet等)声明集合属性,并且永远不要替换使用NHibernate加载的对象的集合属性。
评论中要求的其他信息:
Fabio Maulo(NHibernate首席开发人员)对集合映射here进行了有益的讨论,我强烈建议您阅读。但是,试着简单回答一下你的问题:
但NH如何知道对象之间的关联已被删除?
通常,在使用许多关联的OO模型中工作时,我们会管理父级的关系。也就是说,当孩子在父母的集合中时,孩子被认为与父母相关联。 E.g。
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。