同时插入NHibernate的父级和子级

时间:2011-08-19 15:14:22

标签: nhibernate fluent-nhibernate

我正在尝试使用列表子实体保存(插入)父实体。两个人都使用Guid作为主键。密钥不可为空,并且db中没有设置密钥关系。

保存不起作用,抛出一个异常声明 - 我试图将null保存到Child表中的Parent外键中。

我期待nhibernate为Parent创建一个键,让它的Child对象知道它。这是NHibernate的限制还是使用Guids作为主键?

answer建议您必须手动设置父级,这真的是唯一的方法吗?

以下是我的映射供参考:

父映射:

HasMany(x => x.Children).KeyColumn("ParentKey").Inverse().Cascade.All();

子映射:

 References(x => x.Parent).Not.Nullable().Column("ParentKey");

1 个答案:

答案 0 :(得分:15)

NHibernate并不神奇。它只是一个ORM,如果您的孩子没有将他们的参考设置为父母,为什么它会假设因为父母有一个孩子的列表,孩子的参考,反过来,应该是对父母的引用? / p>

当你声明Child实体没有填充其Parent属性时,我相信你回答了你自己的问题(这意味着它是null,这意味着NHibernate会尝试为父id保存'null'值你的孩子表。)

如果你要使用这些没有NHibernate的对象,那么在添加它们时需要在子实体上设置父引用是有意义的。

编辑:这是您在地图上指定'反向'的情况。如果您要将此次调用移至'Inverse,',则它应该按照您希望的方式工作,因为反向表明另一端 (子实体)负责跟踪关系。这意味着您需要手动设置子项的父项引用。

但是,删除反向语句会导致保存Child(ren),保存父级,然后将Child(ren)的父ID更新为UPDATED。由于您对父ID具有空约束,这意味着它仍然无法正常工作,因为它最初会插入父ID为null的子项。

这两个解决方案是删除此约束,或者只是向Parent添加一个名为 AddChild的方法:

public void AddChild(Child childObj)
{
    childObj.Parent = this;
    Children.Add(childObj);
}

添加另一种名为 RemoveChild的方法:

public void RemoveChild(Child childObj)
{
    if (Children.Contains(childObj))
    {
        Child.Parent = null;
        Children.Remove(childObj);
    }
}

然后,只需使用这些方法添加/删除子项。