添加/删除项目到包集合

时间:2010-09-08 11:26:25

标签: nhibernate nhibernate-mapping

我正在使用nHibernate,并尝试理解包集合。我的数据结构相对简单......

项:

<class name="Entry">
<id name="id" column="EntryId">
    <generator type="guid.comb"/>
</id>
    <property name="Name" column="Name"/>
<bag name="Results" table="Results" cascade="all">
    <key column="EntryId" />
    <one-to-many class="Result"/>
</bag>
</class>

结果:

<class name="Result">
<id name="id" column="ResultId">
    <generator type="guid.comb"/>
</id>
<property name="Score" column="Score" />
<many-to-one name="Entry" class="Entry" cascade="all" />
</class>

我想做的事情似乎不起作用,如下:

Entry entry = new Entry();
entry.Name = "Name";
// have tried saving at this point to:
// dbSession.SaveOrUpdate(entry);
Result result = new Result();
result.Score = 100;

entry.Results.Add(result);
dbSession.SaveOrUpdate(entry);

它似乎是在数据库中创建条目记录,但不是结果记录。在我的数据库中,我将EntryId作为Result表中的外键。同样,我希望能够从集合中删除结果对象,并将其保留到数据库中。我认为级联功能可以解决这个问题,但不确定我做错了什么......

修改

我现在已将结果对象添加到数据库中,但删除似乎不起作用:

Entry entry = Entry.Load(id);
entry.Results.Remove(result);
dbSession.SaveOrUpdate(entry);

我尝试添加cascade =“all-delete-orphan”,但这似乎删除了父级和子级。我只是想从数据库中删除一个条目对象??

4 个答案:

答案 0 :(得分:2)

最后,这归结为我的hbm文件映射不正确。

Entry.hbm.xml

<bag name="Results" table="Result" lazy="false" inverse="true" cascade="all-delete-orphan">
    <key column="EntryId"/>
    <one-to-many class="Result"/>
</bag>

Result.hbm.xml

<many-to-one name="Entry" class="Entry" column="EntryId"/>

我最初在多对一映射上有cascade =“all-delete-orphan”,这是不正确的。发生的事情是所有儿童和父母记录都被删除了。

我现在可以添加和删除以下内容:

Result r = new Result();
Entry entry = new Entry();
// AddResult method sets the Entry object of the Result
// result.Entry = this;
entry.AddResult(r);
session.SaveOrUpdate(entry);

要删除:

entry.Results.Remove(result);
session.SaveOrUpdate(entry);

答案 1 :(得分:0)

要添加到集合,您需要在添加子对象时显式保存它。从集合中删除对象时同上。

所以你会这样做:

entry.Results.Add(result);
session.Save(result);
session.Save(entry);
session.Flush();

外键也必须可以为空。你必须这样做的原因是NHibernate必须首先保存孩子而不与父母联系。然后,当保存父级时,子级上的外键列将使用父级的Id进行更新,从而创建关系。这是因为在第二次操作(保存父级)完成之前,NHibernate可能没有所需的父id键值。

我猜你已经找到了这个部分。

删除以相同的方式出于不同的原因 - 从父集合中删除子节点,然后显式删除子节点,然后更新父节点:

entry.Results.Remove(result);
session.Delete(result);
session.Update(entry);
session.Flush();

您从集合中删除了结果并更新了条目。这只会告诉Nhibernate删除条目和结果之间的关系 - 你从未真正删除过结果对象本身。

答案 2 :(得分:0)

我注意到,在您的集合中,您已将FK列定义为:

<key column="EntryId" />

但是你没有覆盖column中的many-to-one,这意味着你有两个不同的列(Entry和EntryId)用于相同的关系。

这可能是不是......但检查时没有坏处: - )

答案 3 :(得分:0)

如果您使用Mapping by Code,则使用Cascade.All和Cascade.DeleteOrphans选项。与xml映射不同,&#34; all-delete-orphan&#34;没有单一选项。在按代码映射。

 Bag(x => x.Results, c =>
        {
            c.Key(k =>
            {
                k.Column("EntryId");
            });               
            c.Cascade(Cascade.All | Cascade.DeleteOrphans);
        }, r => r.OneToMany())