2011-08-11 3 views
6

이 주어진 : NHibernate에가하는 동안두 개 이상의 테이블에서 NHibernate FetchMany가 깨졌습니까?

namespace TheEntities 
{ 
    [DataContract(IsReference=true)]  
    public class Question 
    { 
     [DataMember] public virtual int QuestionId { get; set; } 
     [DataMember] public virtual string Text { get; set; } 
     [DataMember] public virtual string Poster { get; set; } 

     [DataMember] public virtual IList<QuestionComment> Comments { get; set; } 
     [DataMember] public virtual IList<Answer> Answers{ get; set; } 



     [DataMember] public virtual byte[] RowVersion { get; set; } 
    } 

    [DataContract] 
    public class QuestionComment 
    { 
     [DataMember] public virtual Question Question { get; set; }   

     [DataMember] public virtual int QuestionCommentId { get; set; } 
     [DataMember] public virtual string Text { get; set; } 
     [DataMember] public virtual string Poster { get; set; } 
    } 


    [DataContract(IsReference = true)] 
    public class Answer 
    { 
     [DataMember] public virtual Question Question { get; set; } 

     [DataMember] public virtual int AnswerId { get; set; } 
     [DataMember] public virtual string Text { get; set; } 
     [DataMember] public virtual string Poster { get; set; } 

     [DataMember] public virtual IList<AnswerComment> Comments { get; set; } 

    } 

    [DataContract] 
    public class AnswerComment 
    { 
     [DataMember] public virtual Answer Answer { get; set; } 

     [DataMember] public virtual int AnswerCommentId { get; set; } 
     [DataMember] public virtual string Text { get; set; } 
     [DataMember] public virtual string Poster { get; set; } 
    } 

} 

엔티티 프레임 워크는 답변 QuestionComment, AnswerComment을 중복 객체를 생성하지 않았다. (깊은 두 수준,하지만, 세 가지 관계 사용)

query = query 
    .FetchMany(x => x.Answers) 
    .ThenFetchMany(x => x.Comments) 

이것은 또한 중복 객체를 생성합니다 :

query = query 
    .FetchMany(x => x.Answers) 
    .FetchMany(x => x.Comments); 

public Question OpenQuestion(int id) 
{ 
    var repo = QuestionRepository; 

    var query = repo.All.Where(y => y.QuestionId == id); 

    if (QuestionRepository.GetType() == typeof(EfRepository<Question>)) 
    {     
     query = query 
       .Include("Answers") 
        .Include("Answers.Comments") 
       .Include("Comments"); 

     return query.Single(); 
    } 
    else if (QuestionRepository.GetType() == typeof(NhRepository<Question>)) 
    {     
     // kinda sad, produces duplicate objects 
     query = query 
       .FetchMany(x => x.Answers) 
        .ThenFetchMany(x => x.Comments) 
       .FetchMany(x => x.Comments); 
    } 
    else 
     throw new Exception("Something unsupported"); 

    return query.Single(); 
} 

이도 (세 가지 관계를 이용하여, 세 가지 수준의 깊이) 중복 객체를 생성

이것은 중복 객체를 생성하지 않지만 열심히 로딩하는 것은 2 단계 깊이 만, 2 단계 관계 즉, 질문에서 답변으로 진행됩니다. 질문 할 주석과 응답 할 주석은 별도의 쿼리로 수행됩니다.

query = query 
    .FetchMany(x => x.Answers); 

자 NHibernate 만의 작업은 단지, 왜 ThenFetchMany 만드는 귀찮게 두 관계로 두 가지 수준으로 fetchmany 잘 할 (세 가지 수준에서 사용을하지만, 오류가 중복 된 개체가) 할 수 있다면? 사실 FetchMany조차도 세 관계에 사용하기를 원한다면 쓸모가 없습니다. 중복 객체도 생성합니다.

NHibernate 팀이 ThenFetchMany를 제거하는 데 방해가 될 수 있습니까?

내 매핑에 오류가 없습니다. 가져 오기 전략을 삭제할 때 문제가 없으며 (즉, 중복 객체가 생성되지 않습니다.)

+0

원하는대로 할 수 있습니다.'.TrasformUsing (Transformers.DistinctRootentity)'를 추가하십시오. 이것은 성가신 일이다. – Firo

+0

이 기능은 QueryOver에서만 사용할 수 있습니다.하지만 NH의 Linq (IQueryable)를 사용하고 있습니다. '.TransformUsing'과 같은 NH Linq 확장 메소드는 무엇입니까? –

+0

NHibernate가 JOIN을 수행하는 동안 Entity Framework에서 일부 UNION을 사용하여 쿼리를 작성하기 때문입니다. JOIN은 카티 션 곱을 생성하므로 복제 된 엔티티가됩니다. 이 경우 EF의 전략은 하나의 쿼리에서 많은 정보를 얻을 수 있기 때문에 더 좋습니다. – Sebazzz

답변

6

하면 얻을 수있는 유일한 결과는 Linq에 대한

을 수행

.Distinct() 

에 대한 기준

,174에 대한 QueryOver

.TrasformUsing(Transformers.DistinctRootentity) 

.SetResulttransformer(Transformers.DistinctRootentity) 

편집 : effectivly이 NH의 단점은, 그것은 카티 제품을 발행 할 것이다, 그러나 이것은

repo.All.Where(y => y.QuestionId == id) 
     .FetchMany(x => x.Answers) 
      .ThenFetchMany(x => x.Comments) 
     .Future() 

query = repo.All.Where(y => y.QuestionId == id) 
     .FetchMany(x => x.Comments) 

var result = query.AsEnumerable().Single(); 

이 조금 이상한 보이는 http://ayende.com/blog/4367/eagerly-loading-entity-associations-efficiently-with-nhibernate

볼 수 있지만

을해야 개선 할 수있다
0

시도 :

query.QueryOptions.RegisterCustomAction(c => c.SetResultTransformer(new DistinctRootEntityResultTransformer())); 
+0

NH 2.0 Linq에서만 사용 가능합니다. NH 3.0 Linq가 없습니다. –

+0

NH3.0에서 LINQ가 누락되지 않았습니다. 그것은 자신의 LINQ 제공자입니다. .Query를 통해 액세스 할 수 있습니다. QueryOver에서 Transformer를 사용할 수 있습니다. 그러나 FetchMany를 한 번만 사용하면 안됩니다. – Phill

+0

그래, NHibernate 3 LINQ 지원을 가지고, 그것을 통해 액세스 할 수 있습니다. , LINQ 2에서, 그것은 .Linq 에 있습니다. 사실 NH을 사용하기 시작한 이래로, 나는 HQL과 Linq를 통해서만 질의를한다. (지금은 독점적으로이 작업을하고 HQL 매직 문자열은 싫어한다.) 나는 나의 저장소 인터페이스의'All' 속성에'.Query '을 넣었습니다. 내 말은 'NH 3.0 Linq에서 누락되었습니다.'라는 말입니다. ** Linq **와 ** it ** ;-)라는 단어 사이에 쉼표를 넣는 것을 잊었습니다 ** ** : QueryOptions .RegisterCustomAction' –

관련 문제