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") 
; 
相关问题