在插入之前强制NHibernate级联删除

Jam*_*ley 22 nhibernate nhibernate-mapping nhibernate-cascade

我有一个父对象,它与一个ISet子对象有一对多的关系.子对象具有唯一约束(PageNum以及ContentID- 父对象的外键).

<set name="Pages" inverse="true" cascade="all-delete-orphan" access="field.camelcase-underscore">
    <key column="ContentId" />
    <one-to-many class="DeveloperFusion.Domain.Entities.ContentPage, DeveloperFusion.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</set>
Run Code Online (Sandbox Code Playgroud)

我打的问题是,如果我删除ContentPage从父集合元素,然后添加与同一事务中相同的唯一密钥一个新的...你得到一个违反唯一约束,因为NHibernate的尝试执行插入之前的删除.

有没有办法强制NHibernate首先执行删除?

Stu*_*lds 30

没有选项来指定事务中的操作顺序,因为它是硬编码的,如下所示(来自文档):

SQL语句按以下顺序发出

  • 所有实体插入,使用ISession.Save()以相同的顺序保存相应的对象
  • 所有实体更新
  • 所有集合删除
  • 所有集合元素删除,更新和插入
  • 所有集合插入
  • 所有实体删除,以相同的顺序使用ISession.Delete()删除相应的对象

(例外情况是,保存时会插入使用本机ID生成的对象.)

因此,我可以挑战您回答为什么要添加具有现有标识符的新实体吗?标识符应该对特定的"实体"是唯一的.如果该实体消失了,那么它应该是它的标识符.

另一种选择是对该记录进行更新而不是删除/插入.这使得ID保持不变,因此没有唯一的约束违规(至少在键上),您可以更改所有其他数据,使其成为"新"记录.

编辑:显然我没有完全关注我回答的问题,因为这是对非主键列的唯一约束的问题.

我认为您有两种解决方案可供选择:

  1. Session.Flush()删除后调用将执行到该点的所有会话更改,之后您可以继续执行其余操作(插入新对象).这也适用于事务内部,因此您无需担心原子性.
  2. 创建一个ReplacePage函数,该函数使用新数据更新现有实体,但保持主键和唯一列相同.