流畅的NHibernate一对多级联删除

时间:2012-03-12 19:38:26

标签: c# fluent-nhibernate

我已经看到了很多这个问题,但没有一个解决方案对我有用。

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

类似问题的解决方案是将Inverse添加到父级的HasMany映射中。但是现在出现了这个问题:

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

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

1 个答案:

答案 0 :(得分:11)

在映射中使用“反向”反转了“拥有”父母和孩子之间关系的概念。通过指定“反向”,NH基本上就好像关系的Child侧决定它是否属于Parent,而不是Parent确定它是否具有Child。一个很好的现实世界的例子是学生在大学注册。学生可以选择不再属于大学,并且仍然可以作为一个实体存在并具有意义。这也是学生,而不是学院,谁是决定是否与学院建立或切断这种关系的主要决定者(在现实生活中,是的,有些情况下学院说学生不再受欢迎,但是大学不只是告诉学生信誉良好“你辍学”;是学生告诉大学的。)

缺点是,通过将Parent和Children之间的关系指定为Inverse,NH将关系的“一”侧(Parent)视为在关系的上下文之外不存在的一方。所以,当你清除所有的孩子时,现在没有孩子的父母是“孤儿”,NH会删除它。

这听起来不像你想要的;所以,我会从这种关系中删除反向映射,允许父母与其子女“拥有”这种关系。删除所有孩子,他们成为孤儿和删除,但父母仍在。现在,你有一个问题,即儿童不能被“孤儿”,因为外键不可为空;他们必须属于某种东西。如果您要使用“孤儿删除”级联规则,NH要求子记录的FK可以为空。这是因为孤立删除是一种双遍操作,需要通过将其FK字段设置为null来使记录首先成为孤立状态。然后,NH将运行第二个语句,以从表中删除任何具有NULL FK的记录。因此,即使使用可以为空的FK字段,通过使用具有所需级联规则的NH,也不会有任何具有空FK的记录超过一个过渡期。

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

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

   parent.Children.Clear();
   session.Update(parent);