在NHibernate中存储有序的子集合

时间:2009-12-02 18:57:43

标签: nhibernate

我无法理解我应该与NH实施有序的儿童关系。

在代码世界中,我有:

class Parent
{
    public Guid Id;
    public IList<Child> Children;
}

class Child
{
    public Guid Id;
    public Parent Parent;
}

Parent有一个包含订单的Child[ren]列表。实际上,Children集合将包含将由其他代码强制执行的唯一Child(即,永远不可能将相同的子项添加到集合中两次 - 所以我不会真的护理如果NH集合强制执行此操作

我应该如何实现这两个类的映射?

根据我的理解:

  • Bags没有订单,所以我不想要这个
  • Sets没有订单,但我可以使用order-by来做一些sql命令,但是我的订单是什么?我不能依赖顺序ID。所以我不想要这个?
  • Lists是一个无重复的集合,其中唯一键是PKindex列,所以我确实想要这个吗?

所以,使用list,我有以下内容:

<list cascade="all-delete-orphan" inverse="true" name="Children">
    <key>
        <column name="Parent_id" /> 
    </key>
    <index>
        <column name="SortOrder" /> 
    </index>
    <one-to-many class="Child" /> 
</list>

当我插入一个孩子的父母时,我看到以下SQL:

Insert into Child (id, Parent_id) values (@p0, @p1)

即,为什么不插入SortOrder?

如果我执行SchemaExport,则会在子表上创建SortOrder列。

:(

如果我在关系上设置Inverse="false",我会看到与上面相同的SQL,然后是:

UPDATE "Child" SET Parent_id = @p0, SortOrder = @p1 WHERE Id = @p2

为什么它仍然是INSERT带有inverse="false"的Parent_id,为什么不将SortOrder与inverse="true"一起插入?

我接近这完全错了吗?

假设这是有效的,如果我这样做也是如此:

parentInstance.Children.Remove(parentInstance.Children[0]);

保存父级并重新加载,list在位置0中将为空,而不是将其余部分移动?

由于

1 个答案:

答案 0 :(得分:1)

Inverse=true表示NHib不会尝试保存实际的集合。但是,它仍然级联通过集合到包含的实体上的保存操作,其中包括持久的瞬态实例。这就是为什么你得到一个没有SortOrder的插入的原因 - NHib会持久化你的瞬态Child对象。

a similar question解决方案涉及转移到<bag>映射,但这会失去<list>的排序质量。

现在我使用<list>之前使用<many-to-many>映射,并且它运行良好。有两个SQL插入调用 - 一个包含子实体的表,另一个包含到链接表。我怀疑在你的情况下,即使两个电话都在同一张桌子上,NHib仍然采用相同的策略。

最后,如果删除索引0处的项目,那么最终会得到一个空值。

总的来说,我建议:1)转移到集合的<bag>映射,并维护排序顺序的特定属性;或者2)转移到集合中的<many-to-many>映射。