2010-09-08 99 views
2

我正在与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作为结果表中的外键。同样,我希望能够从集合中删除结果对象,并将其保留到数据库中。我以为级联功能,照顾了这一点,但不知道我做错了......

编辑

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

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

我已经尝试添加级联=“所有删除孤儿”,但这似乎删除父母和子女。我只想要它从数据库中删除一个入口对象?

回答

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"/> 

我本来级联= “全删除,孤儿” 在很多一对一的映射,从而是不正确的。发生的是所有的孩子和父母的记录被删除。

我现在可以添加和删除下列要求:

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); 
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删除条目和结果之间的关系 - 您从未真正删除过结果对象本身。

+0

我也这么认为,但事实并非如此。我提供了答案。 – mickyjtwin 2010-09-15 07:01:47

0

我注意到,你的收藏中,定义了FK列:

<key column="EntryId" /> 

但你是不是在你的many-to-one重写column,这意味着你有两个不同的列(进入和ENTRYID)为同样的关系。

这可能与否或...但它不伤害检查:-)

0

如果您正在使用制图代码并使用两种Cascade.All和Cascade.DeleteOrphans选项。与xml映射不同,“按代码映射”中没有“all-delete-orphan”的单一选项。

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