2013-08-22 34 views
3

我有一個雙向關聯是這樣的:NHibernate的:級聯保存到孩子不插入

public class Parent 
{ 
    public int ParentId {get; set;} 
    ...other properties 
    public IEnumerable<Child> Children {get; set;} 
} 

public class Child 
{ 
    public int ChildId {get; set;} 
    ...other properties 
    public Parent Parent {get; set;} 
} 

流利的映射如下:

父映射

Id(x => x.ParentId, "PARENT_ID").GeneratedBy.Identity(); 
.. other mappings 
HasMany(x => x.Children).Cascade.All().KeyColumn("PARENT_ID"); 

兒童繪圖

Id(x => x.ChildId, "CHILD_ID").GeneratedBy.Identity(); 
.. other mappings 
References(x => x.Parent).Column("PARENT_ID").Cascade.None(); 

當我執行這樣的代碼:

Parent parent = new Parent{ ..set some properties... }; 
parent.Children = new[] { new Child{ ..set some properties.. }; 
session.Save(parent); 

我得到一個違反外鍵約束,因爲當它試圖插入孩子NHibernate的不是孩子記錄的PARENT_ID列設置爲新的ID。

很明顯,我已要求在Parent的映射中級聯。 NHibernate試圖保存孩子,但爲什麼沒有設置ID?

回答

7

您需要進行兩項更改。

  1. 您需要.Inverse()HasMany(x => x.Children)。有關更多信息,請參閱my answer explaining inverse
  2. 您還需要將child.Parent = parent;添加到保存實體的代碼中。

就你而言,這兩種關係是相互衝突的。 parent.Children包含child,這意味着NHibernate應該堅持Child.PARENT_ID作爲父母的ID,但child.Parent爲空,這意味着NHibernate應該堅持Child.PARENT_ID爲空。顯然child.Parent贏了。實際上,更可能的是他們都贏了。 NHibernate的可能是執行兩個查詢類似這些...

/* This is what child.Parent says we should save. 
    This query will fail because PARENT_ID is NOT NULL. */ 
insert into Child (CHILD_ID, PARENT_ID) values (@childId, null); 

/* This is what parent.Children says we should save. */ 
update Child set PARENT_ID = @parentId where CHILD_ID = @childId; 

如果使兩個更改我上面的建議,NHibernate的將是能夠正確地保存這一點,就像這樣:

insert into Child (CHILD_ID, PARENT_ID) values (@childId, @parentId); 
+0

所以我需要在保存之前設置關係的雙方? – David

+1

您至少需要設置關係的非反面:'child.Parent'。如果'parent.Children'是相反的,那麼將'child'添加到'parent.Children'是可選的,但爲了保持模型的一致性是一個好主意。另一條路線是徹底擺脫'child.Parent'屬性(你不能做一個「多對一」反轉),並且把HasMany(x => x.Children)保留爲非反轉。無論選擇哪條路線,您都必須*設置非反比關係的值。 –

+0

如何刪除child.Parent屬性並在hibernate.config中進行映射? – misha

相關問題