1

我使用流利NHibernate和我試圖映射一個多對多的屬性,只是繞過連接表。棘手的是,連接表有一列確定它是什麼類型的關係。流利NHibernate的HasManyToMany鑑別器列指定的關係類型

爲了這個問題,我們假設我有一個人表和一個關係表。

PersonTable (PersonId, Name, etc) 
RelationTable (RelationType, PersonIdA, PersonIdB) 

我想在Person類中爲每種關係類型引入一個集合屬性,例如,節能傑克在RelationTable我約翰的新女婿的時候基本上

Person john = PersonDAO.GetByName("John"); // the Sons and Daughters are loaded fine based on mappings above 

john.Sons.Add(new Person("Jack")); // let's add a new son 
PersonDAO.Save(john);    // this fails because RelationType is null 

:兒子,女兒等

HasManyToMany<Person>(x => x.Sons) 
    .Table("RelationTable") 
    .ParentKeyColumn("PersonIdA") 
    .ChildKeyColumn("PersonIdB") 
    .Where("RelationType='A_IS_FATHER_OF_B_BOY'"); 

HasManyToMany<Person>(x => x.Daughters) 
    .Table("RelationTable") 
    .ParentKeyColumn("PersonIdA") 
    .ChildKeyColumn("PersonIdB") 
    .Where("RelationType='A_IS_FATHER_OF_B_GIRL'"); 

上述映射正在從數據庫中讀取,但不能用於插入,例如需要將RelationType填充爲「A_IS_FATHER_OF_B_BOY」,這種情況目前尚未發生。 指令.Where(「RelationType ='A_IS_FATHER_OF_B_BOY'」)只適用於加載,但不適用於保存。

任何想法?我認爲這有點類似於子類的Discriminator屬性。

任何幫助表示讚賞。謝謝。

+0

*在您得到您的答案之前,我會建議避免多對多,如果可能的話。如果你喜歡閱讀更多[這裏](http://stackoverflow.com/a/21136089/1679310)或[這裏](http://stackoverflow.com/a/16827671/1679310)* – 2014-12-02 06:50:37

+0

@RadimKöhler,我已閱讀通過您提供的鏈接。我實際上確實將RelationTable與2個多對一引用映射爲Person(如PersonA和PersonB)。使用一對多(HasMany),你怎麼建議我在Person類中映射兒子和女兒(都列表),同時考慮到上面的鑑別器值?謝謝。 – 2014-12-02 23:13:32

回答

1

我要說,正如您在您的評論中指出:

其實我有RelationTable映射2所many-to-one引用的人(如人物角色和PersonB)。使用one-to-many(的hasMany),怎麼那麼你建議我映射的兒子和在Person類的女兒(均List<Person>)考慮到如上

鑑別值,所以在我眼中的配對對象將是

public class PersonRelation 
{ 
    // the pairing table must contain the key column, surrogated ID 
    public virtual int Id { get; protected set; } // this is a must. 

    public virtual Person Parent { get; set; } 
    public virtual Person Child { get; set; } 
    public virtual string RelationType { get; set; } 
} 

必須有此表的關鍵。只需注入一些IDENTITY列與SQL Server ..但有一些代理(獨立的業務領域)的關鍵。

這裏是我們的Person實體

public class Person 
{ 
    IList<PersonRelation> _sons; 
    IList<PersonRelation> _daughters; 
    .., 
    public virtual IList<PersonRelation> Sons 
    { 
     get { return _sons ?? (_sons = new List<PersonRelation>()); } 
     set { _sons = value; } 
    } 
    public virtual IList<PersonRelation> Daughters 
    { 
     get { return _daughters?? (_daughters= new List<PersonRelation>()); } 
     set { _daughters= value; } 
    } 
} 

的兒子映射(女兒將是相同的)

HasMany<PersonRelation>(x => x.Sons) 
    // .Table("RelationTable") // not needed - part of PersonRleation mapping 
    .KeyColumn("PersonIdA") 
    .Where("RelationType='A_IS_FATHER_OF_B_BOY'") 
    .Inverse() 
    .Cascade.AllDeleteOrphan() 
; 

這將工作,如果我們將始終保證,那將兒子當,我們也正確設置RelationType

var parent = ...; // new, loaded 
var child = ...; // new, loaded 

var relation = new PersonRelation 
{ 
    Parent = parent; 
    Child = child; 
    RelationType = "A_IS_FATHER_OF_B_BOY"; 
}; 

parnet.Sons.Add(relation); 

這m烏斯是Businese層AddSon()的一部分,或者它可以是公共POCO方法...

注意:我們還可以映射關係的反向端...即使沒有關係類型過濾:

public class Person 
{ 
    ... as above 
    public virtual IList<PersonRelation> Parents { get; set; } 


HasMany<PersonRelation>(x => x.Parents) 
    // instead of this 
    // .KeyColumn("PersonIdA") 
    // we need this column 
    .KeyColumn("PersonIdB") 
; 
相關問題