NHibernate:从集合中移除vs关联和级联样式

use*_*375 3 nhibernate

我无法理解NHibernate如何知道从关联中删除的对象(然后执行像delete-orphant这样的级联样式).我的意思是,在数据库级别,如果我想删除一个关联,我必须实际登录并删除一些FK.在NH世界中这是怎么发生的?我是否重新映射我的课程,删除以前建立的父/子关联(关系),NH做比较分析,挖掘某些事情已经改变然后采取适当的行动?在这篇文章中, Ayende讨论了不同的级联风格和删除 - 或者描述为"... ...除此之外,当一个对象从被处理中移除而没有与另一个对象(孤儿)相关时,也删除它......"这种删除是如何发生的?

Phi*_*rdt 5

NHibernate监视NHibernate会话中对象所拥有的所有映射集合.当您进行更改(添加/删除)时,NHibernate将它们标记为脏.当需要刷新更改时,它会比较脏集合中的元素,并能够识别已添加和删除的项目.根据集合的级联选项,NHibernate可能会将这些更改持久保存到数据库中.

这就是为什么你应该总是使用接口(IList,ISet等)声明集合属性,并且永远不要替换使用NHibernate加载的对象的集合属性.

评论中要求的其他信息:

有通过集合映射的法比奥Maulo(NHibernate的首席开发人员)一个有用的讨论在这里,我会强烈建议阅读.但是,试着简单回答一下你的问题:

但NH如何知道对象之间的关联已被删除?

通常,在具有许多关联的OO模型中工作时,我们管理父级的关系.也就是说,当孩子在父母的集合中时,孩子被认为与父母相关联.例如

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

类似地,从集合中删除项会破坏关联(假设使用了正确的映射属性)

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.
Run Code Online (Sandbox Code Playgroud)

这与我们通过子行上的外键管理孩子之间关系的关系世界中的工作方式相反.

为了更详细的理解,没有什么比下载NHibernate源代码,创建一个简单的测试用例,然后在调试器中单步执行.

"这就是为什么......"背后的原因是什么?

NHibernate在管理关联集合时需要注意很多事情.它通过使用自己的集合类来实现这一点,这些集合类可以跟踪它们是否是脏的,它们从数据库加载时的状态以及许多其他很酷的东西.如果你替换那些对象,那么NHibernate会失去这种能力.所以,例如,如果你想要摆脱集合中的所有项目,你应该做:

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

你永远不应该这样做:

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

为了进一步阅读,您可能还想看看这个.