자체 합의 관계에 추가 특성이있을 때 nhibernate 매핑
-
03-07-2019 - |
문제
동일한 클래스의 다른 인스턴스에 클래스를 어떻게 매핑합니까? 그 관계에 속성 자체가있을 때?
테이블 사람에게 매핑되는 사람이라는 수업이 있습니다.
PersonID PersonName PersonAge
----------------------------------
1 Dave Dee 55
2 Dozy 52
3 Beaky 45
4 Mick 55
5 Tich 58
나는 Personperson이라는 가입 테이블을 사용하는 사람과 사람 사이의 많은 관계를 원합니다.
PersonPersonID PersonID RelatedPersonID RelationshipID
--------------------------------------------------------
1 1 5 1
2 3 4 2
3 2 1 3
개인 테이블의 다음 속성을 원합니다.
RelationshipID RelationshipName
--------------------------------
1 Colleague
2 Manager
3 Tutor
이 질문 그리고 링크된다 Billy McCafferty의 게시물 사람의 관계는 개인 테이블의 추가 열이기 때문에 개인 관계를 정상적인 엔티티 자체로 홍보해야한다고 설명합니다. 그러나 자체 결합 일 때 무엇을 설명하지 않습니다. 차이점은 내가 모든 관련자들에게 요청하면 데이브 디 (ID = 1), 내가 얻어야 할뿐만 아니라 티쉬 (ID = 5), 그러나 나도 얻어야합니다 어리석은 (ID = 2) Dave Dee도 관련 인기 열에 있기 때문에 (ID = 2).
내 솔루션은 지금까지 내 개인 수업에 두 가지 속성을 갖는 것입니다.
public virtual IList<PersonPerson> PersonPersonForward {get;set;}
public virtual IList<PersonPerson> PersonPersonBack {get;set;}
private List<PersonPerson> personPersonAll;
public virtual List<PersonPerson> PersonPersonAll
{
get
{
personPersonAll = new List<PersonPerson>(PersonPersonForward);
personPersonAll.AddRange(PersonPersonBack);
return personPersonAll;
}
}
그리고 HBM에서 다음과 같이하십시오.
<bag name="PersonPersonForward" table="PersonPerson" cascade="all">
<key column="PersonID"/>
<one-to-many class="PersonPerson" />
</bag>
<bag name="PersonPersonBack" table="PersonPerson" cascade="all">
<key column="RelatedPersonID"/>
<one-to-many class="PersonPerson" />
</bag>
이것은 사소하고 어리석은 것처럼 보입니다. nhibernate는 일반적으로 대부분의 일상적인 문제에 대한 우아한 솔루션을 가지고 있습니다. 위의 현명한 방법 이이 작업을 수행합니까, 아니면 더 좋은 방법이 있습니까?
해결책
나는 그렇게 할 것이라고 생각하지만, 이런 식으로 모델링하는 것은 약간의 '서투른'것이라고 생각합니다. 내 말은 : 당신은 특정 사람이 관련된 사람을 가지고 있지만, 당신은 또한 '역 관계'도 있습니다.
이것이 정말로 필요합니까? 이 배출을 제거하고 대신 주어진 사람과 어떤 관계가있는 모든 사람을 되 찾을 수있는 개인의 양의 방법을 지정하는 옵션이 아닙니까?
흠, 이것은 약간 모호하게 들릴 수 있습니다. 여기에 일부 코드가 있습니다 (간결성을 위해서는 '가상'수정 자 등을 제외했습니다 ... (또한 수정자를 갖지 않는 것이 좋습니다. 시간의 %, 나는 클래스 맵핑에서 'Lazy = false'를 지정합니다).
public class Person
{
public int Id {get; set;}
public string Name {get; set;}
public IList<PersonPerson> _relatedPersons;
public ReadOnlyCollection<PersonPerson> RelatedPersons
{
get
{
// The RelatedPersons property is mapped with NHibernate, but
// using its backed field _relatedPersons (can be done using the
// access attrib in the HBM.
// I prefer to expose the collection itself as a readonlycollection
// to the client, so that RelatedPersons have to be added through
// the AddRelatedPerson method (and removed via a RemoveRelatedPerson method).
return new List<PersonPerson) (_relatedPersons).AsReadOnly();
}
}
public void AddRelatedPerson( Person p, RelationType relatesAs )
{
...
}
}
보시다시피, 사람 클래스에는 하나의 컬렉션 만 남았습니다. 즉,이 사람이 가진 관계를 나타내는 사람 대상의 모음입니다. 주어진 사람과 관계가있는 사람을 얻기 위해서는 개인 반복에 대한 특정 방법을 만들 수 있으며, 개인 수업에 컬렉션을 갖는 대신 해당 사람을 반환하는 데 도움이됩니다. 나는 이것이 성능을 향상시킬 것이라고 생각합니다.
public class NHPersonRepository : IPersonRepository
{
...
public IList<Person> FindPersonsThatHaveARelationShipWithPerson( Person p )
{
ICriteria crit = _session.CreateCriteria <Person>();
crit.AddAlias ("RelatedPersons", "r");
crit.Add (Expression.Eq ("r.RelatedWithPerson", p));
return crit.List();
}
}
'역 참조'는 개인 수업의 구성원이 아닙니다. 저장소를 통해 액세스해야합니다. 이것은 또한 Eric Evans가 그의 DDD -Book에서 말하는 것입니다. 어떤 경우에는 저장소에 특수한 방법을 사용하여 관련 객체에 액세스 할 수있는 (= 관련 객체)를 가지고 다닐 수있는 것이 좋습니다. 객체 자체로.
나는 코드를 테스트하지 않았고 여기에 입력했기 때문에 구문 오류 등을 확인하지 않았지만 이것을 어떻게 볼 수 있는지에 대해 조금 명확히해야한다고 생각합니다.