Fluent NHibernate一对多级联删除

本文关键字:删除 级联 一对多 NHibernate Fluent | 更新日期: 2023-09-27 18:27:27

我经常看到这个问题,但没有一个解决方案对我有效。

我在C#中有一个一对多的关系,用流利的NHibernate映射到MS SQL。当我试图删除一个子元素时,NHibernate试图通过将外键设置为NULL来做到这一点,这当然会引发错误。

类似问题的解决方案是将Inverse添加到父对象的HasMany映射中。但是现在有一个问题:

var parent = //something
parent.Children.Clear();
session.Update(parent);

这将导致整个父项被删除!为什么?

Fluent NHibernate一对多级联删除

在映射中使用"Inverse"颠倒了谁"拥有"父子关系的概念。通过指定"反向",NH基本上就好像关系的子方决定它是否属于父方,而不是父方决定是否拥有子方。现实世界中一个很好的例子是学生被大学录取。一个学生可以选择不再属于一所大学,并且作为一个实体仍然存在和有意义。学生,而不是学院,是决定是否与学院建立或切断这种关系的主要决定者(在现实生活中,是的,有些情况下,学院会说学生不再受欢迎,但学院不仅仅告诉一个有良好声誉的学生"你要辍学",而是学生告诉学院这一点)。

简而言之,通过将Parent和Children之间的关系指定为Inverse,NH将关系的"一方"(Parent)视为不能存在于关系上下文之外的一方。因此,当您清除所有子项时,现在没有子项的父项将成为"孤儿",NH将其删除。

这听起来不像你想要的;因此,我将从该关系中删除反向映射,允许父对象"拥有"与其子对象的关系。删除所有子项,它们将成为孤儿并被删除,但父项仍然存在。现在,您遇到的问题是Children不能成为"孤儿",因为外键不可为null;它们必须属于某种东西。如果要使用"孤立删除"级联规则,NH要求子记录的FK可以为null。这是因为孤立删除是一个两步操作,需要通过将记录的FK字段设置为null来首先孤立记录。NH将运行第二条语句,从表中删除任何FK为NULL的记录。因此,即使有一个可为null的FK字段,通过使用具有所需级联规则的NH,在超过一个过渡期的时间内,也不会有任何具有null FK的记录。

如果这是不可接受的,您将不得不从级联规则中删除孤立删除,并手动删除每个记录以及将其从会话中删除。

foreach(var child in parent.Children)
      session.Delete(child);
   parent.Children.Clear();
   session.Update(parent);