20

我有一個問題,試圖找出一個多對多的關係,其中關係的兩邊引用相同的實體。我使用流利NHibernate和NH3.1。流利nhibernate - 在同一個實體上的多對多關係映射

基本上,情況是這樣的 - 我有一個類別,它可以有多個父母。因此,一個類別具有多個其他類別作爲父母,以及多個其他類別作爲其子類。

HasManyToMany(x => x.ParentCategories).AsBag().Table("parentcategorychildren").ParentKeyColumn("ChildID").ChildKeyColumn("ParentID").Cascade.SaveUpdate(); 
HasManyToMany(x => x.ChildrenCategories).AsBag().Table("parentcategorychildren").ParentKeyColumn("ParentID").ChildKeyColumn("ChildID").Inverse(); 

但是,當我嘗試建立了工廠,我得到以下錯誤:

The relationship Category.ChildrenCategories to Category.ChildrenCategories has Inverse specified on both sides. Remove Inverse from one side of the relationship.

什麼我發現奇怪的是爲什麼會提「Category.ChildrenCategories」到Category.ChildrenCategories,而不是ParentCategories?

任何幫助將不勝感激!

我剛剛爲此創造了一筆賞金,因爲它對我來說很重要。請,我對「你不能做這個」感興趣,作爲答案。

+0

我們有完全相同的問題。答案將不勝感激。 – 2011-05-11 18:11:33

+0

如果確實是FNH中的一個錯誤,那麼您可以始終使用傳統的xml映射或答案中提供的解決方法。 – Vadim 2011-05-12 21:12:08

+0

我爲此提出了[問題](http://fluentnhibernate.lighthouseapp.com/projects/33236-fnh/tickets/212-inverse-validation-fails-on-self-referential-relationships)。我們將盡快解決。 – 2011-05-16 11:43:59

回答

12

這很可能是一個FNH錯誤,它很可能已經在最新的FNH source code中修復。使用FNH1.0和NH2.1時沒有問題。等效HBM映射FNH1.2和NH3.1效果很好:

<bag name="ParentCategories" cascade="all" table="parentcategorychildren"> 
    <key column="ChildID" /> 
    <many-to-many column="ParentID" class="Category" /> 
</bag> 

<bag name="ChildrenCategories" inverse="true" table="parentcategorychildren"> 
    <key column="ParentID" /> 
    <many-to-many column="ChildID" class="Category" /> 
</bag> 

編輯: 在FNH源代碼挖後,我發現了一個解決方法。比方說,你的配置是這樣的:

.Mappings(m => { 
    m.FluentMappings.AddFromAssemblyOf<Category>(); 
}) 

倒黴的代碼可以通過這種結構來抑制:

.Mappings(m => { 
    var persistenceModel = new PersistenceModel(); 
    persistenceModel.AddMappingsFromAssembly(typeof(Category).Assembly); 
    persistenceModel.ValidationEnabled = false; // this makes the trick 
    m.UsePersistenceModel(persistenceModel); 
}) 
+0

你可以在這裏看到檢查代碼https://github.com/jagregory/fluent-nhibernate/blob/release-1.2/src/FluentNHibernate/Visitors/ValidationVisitor.cs,它似乎仍然是最新版本的FNH。有沒有辦法在一張地圖上禁用驗證? – 2011-05-12 16:09:09

+0

是的,它是1.2標籤。最新的代碼是在主分支(https://github.com/jagregory/fluent-nhibernate/blob/master/src/FluentNHibernate/Visitors/ValidationVisitor.cs),但我沒有測試從主分支的版本,所以我不知道它是否已經在那裏(只是猜測)。我不知道如何禁用單個MapClass的驗證,但只有兩個驗證。不需要的,並檢查Id是否被映射。我會在沒有他們的情況下過着幸福的生活:)。 – 2011-05-12 16:22:38

+0

我可能會誤解正在發生的事情,但看起來master分支已經過時,它缺少2.1中的提交。我沒有看到在任何分支中解決這個問題。 – 2011-05-12 19:31:35

6

這是人際關係的功能NHibernate 2.1的驗證/配對的問題。 FNH pairs up relationships,然後validates that only one side of the relationship has .Inverse() specified。因爲兩個參考(父/子)都屬於同一類,所以它們在配對時都是候選匹配。在那種情況下,FNH matches on name similarity。因此,他們各自與自己配對,而不是彼此配對。因此,然後將.Inverse()放在任何一個觸發驗證(雙方的兩側是相反的關係)。

應該可以在FluentMappingsContainer上使用OverrideBiDirectionalManyToManyPairing()方法進行更正。理論上,這將允許您明確配對兒童和父母的關係。但是,在FNH 2.1中存在一個錯誤,並且絕不會調用覆蓋回調。 (The callback value is captured before it can be set by the method)。

作爲解決方法,您可以禁用FNH中的所有驗證。有only two validations。首先,雙方的關係沒有.Inverse()。其次,Id被映射到每個實體上。我發現禁用驗證的最徹底的方法是:

.Mappings(m => { 
    var persistenceModel = new PersistenceModel() { ValidationEnabled = false }; 
    m.UsePersistenceModel(persistenceModel) 
    .FluentMappings.AddFromAssemblyOf<Category>(); 
}) 

這種方法可以讓你禁用驗證,但仍使用FluentMappings配置的全面表現。

+0

是的,但其他任何錯誤也會被抑制,我認爲這可能會對未來對類映射的更改產生疑問,而且沒有人注意到這一點。 – 2011-05-16 09:36:12

+0

斑點!我(顯然)不考慮這種情況。我爲此創建了[問題](http://fluentnhibernate.lighthouseapp.com/projects/33236-fnh/tickets/212-inverse-validation-fails-on-self-referential-relationships),我們將它儘快排序。 – 2011-05-16 11:42:08

+0

卡爾,是的,禁用驗證將禁用我在我的答案中闡述的兩項檢查。隨着更多驗證的添加,這可能會很麻煩。然而,Jakub的答案是禁用相同的一組驗證,只是代碼略有不同。 – 2011-05-16 16:45:39

0

是的,在我看來,這很可能是FNH中的一個錯誤,因爲我直接使用NHibernate而不使用Fluent NH並嘗試它。但是,因爲我已經使用FNH建立了一個系統,所以我不能僅僅回覆到不使用它。

我所做的是我爲自己創造的一種「中間班」自己,這種關係通常是自動生成的。我創建了一個ContentPage_ChildLink頁面,該頁面鏈接ParentsChildren類別。這讓我和FNH一起工作並解決了這個問題:)

基本上這個ContentPage_ChildLink會有兩個字段,ChildIDParentID。然後,我可以單獨設置'逆向'關係,沒有任何問題。

FNH的問題似乎是當你有多對多的關係時,雙方都是同一類,唯一我能想到的情況是允許多個父母的層次結構。

+0

我們遇到的情況是銀行賬戶,其中一些賬戶被關閉,並且資金被轉入其他賬戶。這從帳戶到帳戶創建了多對多。 – 2011-05-16 16:47:49

+0

您需要創建另一個類來鏈接銀行帳戶,以便解決該錯誤。你可以有一個'AccountLink'類,它具有'MainAccountID'和'LinkedAccountID'。 AccountLink將具有一對多集合「LinkedAccounts」,其具有一對多關係「AccountLink」表。您可以通過執行MainAccount.LinkedAccounts [0] .LinkedAccount來遍歷關係。希望能幫助到你 ! – 2011-05-17 09:39:53

相關問題