我正在对正在尝试更新已断开连接的实体的代码进行故障排除,该实体具有对子实体的未初始化引用。目的是仅更新Parent上的属性而不加载子项。
HasMany(x => x.ChildEntities)
.KeyColumn("ChildEntityId")
.Table("ChildEntity")
.Not.LazyLoad()
.Inverse()
.Cascade.All().AsBag();
调用Session.Update(父级)时,将执行两个更新语句。第一个按预期更新父对象。
update Parent set ... where ParentId = 12345
第二次更新让我感到困惑......
update ChildEntity set ParentId = null where ParentId = 12345
为什么NHibernate会发出第二个SQL语句?我意识到ChildEntities是未初始化的,并且NHibernate可能正在尝试强制执行Parent的状态,但我似乎无法调整映射以不进行第二次更新。我已经尝试过Merge,延迟加载,各种级联选项等,但没有成功。在尝试提交时,会话中唯一连接的实体是Parent。
请注意,我通常通过检索启用了延迟加载的实体,然后在将NHibernate持久保存到数据库之前从断开连接的对象(DTO或实体)映射到连接的实体来实现此目的。在我提出另一种方法之前,我想了解上述原因无法解决的原因。
答案 0 :(得分:4)
这很烦人。
快速搜索NHibernate源代码中的“无法删除集合”显示在一个块中,该块只能在!isInverse(AbstractCollectionPersister.cs)中执行。这引起了我的注意,因为映射代码在该集合上明确设置了Inverse。
如果Inverse为false且集合为空,则NH对子表执行更新,将外键设置为null,其中外键等于父ID。
Fluent配置为自动映射给定命名空间中的所有实体。假设自动映射会忽略任何带有手动映射的内容。快速检查Fluent生成的hbm.xml文件,确认没有设置Inverse。我将Parent添加到明确从Auto Mapping中排除的实体列表中,一切都开始工作。
.IgnoreBase<Parent>()