1

저는 Fluent NHibernate를 사용하고 있으며, 단순히 join 테이블을 우회하는 다 대다 속성을 매핑하려고합니다. 까다로운 점은 조인 테이블에 어떤 유형의 관계가 있는지 결정하는 열이 있다는 것입니다.Fluent NHibernate hasManyToMany discriminator column이 관계 타입을 지정합니다.

이 질문의 목적을 위해 사람 테이블과 관계 테이블이 있다고 가정 해 봅니다.

각 관계 유형에 대해 Person 클래스에 컬렉션 속성을 도입하려고합니다. 아들, 딸은

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'"); 

위의 매핑

예를 들어, 삽입하지 데이터베이스에서 읽기 위해 노력되지만, 등 :

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 

을 기본적으로 RelationTable I 존의 새로운 아들로 잭을 저장할 때 현재 발생하지 않는 RelationType을 "A_IS_FATHER_OF_B_BOY"로 채워야합니다. 지시문 .Where ("RelationType = 'A_IS_FATHER_OF_B_BOY'")는로드에만 유효하지만 저장에는 유효하지 않습니다.

아이디어가 있으십니까? 나는 이것이 하위 클래스의 Discriminator 속성과 다소 비슷하다고 생각한다.

도움을 주시면 감사하겠습니다. 감사.

+0

* 답변을 얻으려면 가능한 경우 many-to-many를 피하는 것이 좋습니다. 당신이 좋아한다면, 더 읽기 [여기] (http://stackoverflow.com/a/21136089/1679310) 또는 [여기] (http://stackoverflow.com/a/16827671/1679310) * –

+0

@ RadimKöhler, 나는 읽었다. 제공 한 링크를 통해 필자는 실제로 RelationTable을 Person에 대한 2 개의 다 대일 참조 (PersonA와 PersonB)로 매핑했습니다. 일대 다 (HasMany)를 사용하여, 어떻게 위에서와 같은 판별 자 값을 고려하여 Person 클래스의 Sons and Daughters (둘 다 List )를 매핑하는 것이 좋습니다. 감사. –

답변

1

나는 당신의 의견에서 지적한대로 정확하게 말할 것입니다 :

내가 실제로 RelationTable이 (인물과 PersonB 같은) 사람 2 many-to-one 참조 매핑이 없습니다. 사용 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; } 
} 

반드시이 테이블의 키가 있어야합니다. SQL Server에 IDENTITY 열을 삽입하면되지만 비즈니스 도메인 독립 키로 대용 할 수 있습니다. 여기

는 아들에 대한 매핑이 (딸이 같은 것) 우리 사람의 실체

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() 
; 

우리가 항상 보장한다면, 작동 할 것이다 아들을 추가 할 때 , 우리도 적절하게 설정합니다. 관계 유형

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") 
; 
관련 문제