我正在使用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”,但这似乎删除了父级和子级。我只是想从数据库中删除一个条目对象??
答案 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())