2010-01-16 2 views
3

데이터베이스에 3 개의 테이블을 생성하고 데이터를 입력했습니다. 3 개의 테이블에는 모두 외부 키가 함께 있습니다. 아래는 테이블 클래스와 매핑입니다. 마지막에 나열된 쿼리를 실행하면 IList <>을 가져오고 모든 3 개의 테이블의 데이터를 갖게됩니다. 그러나, 내 HQL 쿼리는 최상위 테이블에서만 발생합니다. 최상위 테이블에서 결과를 어떻게 다시 얻을 수 있습니까? HQL 쿼리를 사용하는 테이블 대신 모든 테이블에서 데이터 가져 오기 1 테이블의 데이터 만 가져와야합니다.

내 클래스입니다 :

public class Technology 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Name { get; set; } 
    public virtual int SortOrder { get; set; } 
    public virtual string Abbreviation { get; set; } 
    public virtual IList<TechnologyDescription> TechnologyDescriptions { get; private set; } 

    public Technology() 
    { 
     TechnologyDescriptions = new List<TechnologyDescription>(); 
    } 

    public virtual void AddTechnologyDescription(TechnologyDescription technologyDescription) 
    { 
     technologyDescription.Technology = this; 
     TechnologyDescriptions.Add(technologyDescription); 
    } 
} 

public class TechnologyDescription 
{ 
    public virtual int Id { get; private set; } 
    public virtual Technology Technology { get; set; } 
    public virtual string Description { get; set; } 
    public virtual DescriptionType DescriptionType { get; set; } 
} 

public class DescriptionType 
{ 
    public virtual int Id {get; private set;} 
    public virtual string Type { get; set; } 
} 

These are my mapping objects: 

public class TechnologyMap : ClassMap<Technology> 
{ 
    public TechnologyMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Name); 
     Map(x => x.SortOrder); 
     Map(x => x.Abbreviation); 
     HasMany(x => x.TechnologyDescriptions) 
       .Inverse() 
       .Cascade.All(); 
    } 
} 

public class TechnologyDescriptionMap : ClassMap<TechnologyDescription> 
{ 
    public TechnologyDescriptionMap() 
    { 
     Id(x => x.Id); 
     References(x => x.Technology); 
     Map(x => x.Description); 
     References(x => x.DescriptionType); 
    } 
} 

public class DescriptionTypeMap : ClassMap<DescriptionType> 
{ 
    public DescriptionTypeMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Type); 
    } 
} 

그리고 이것은 내 HQL 코드입니다 : 당신이 할 수있는, 그것은 HQL을 사용하여 가능하면 나도 몰라

IQuery q = session.CreateQuery("from Technology T"); 
IList technologies = q.List(); 
+0

감사 : 게으른 로딩이 기본 유창 매핑 될 것처럼

최근 같습니다. 당신의 반응이 나를 도왔습니다. 감사! –

답변

1

하지만, NHibernate에의 기준 API를 사용하여 다음을 수행하십시오 :

ICriteria criteria = session.CreateCriteria (typeof(Technology)); 

criteria.SetFetchMode ("TechnologyDescriptions", FetchMode.Lazy); 

var list = criteria.List<Technology>(); 

그러나 이것은 실제로 원하는 것이 아닙니다. TechnologyDescriptions는 지금 가져 오지 않지만, 일단 액세스하면 (즉, 처음으로 TechnologyDescriptions 속성을 호출 할 때) 가져옵니다.

NHibernate로 작업 할 때는 '데이터'를 생각해서는 안됩니다. 오히려, 당신은 '엔티티'의 관점에서 생각해야합니다.
엔티티를 검색 할 때 엔티티를 직접 또는 게으른 방식으로 검색하려고합니다. 엔티티를 부분적으로 검색하는 것은 불가능하며 이는 매우 분명합니다. NHibernate는 엔티티를 저장할 때 부분적으로 검색 한 엔티티와 어떻게해야합니까?

내 마음에 떠오르는 다른 것 : 기술을 검색하려고한다고 가정합니다. 개요 나 이와 비슷한 내용을 표시하려고하기 때문에 관련이 없습니다. 그런 경우 '변환'을 살펴 봐야합니다. 당신은 예를 들면 다음과 같습니다 TechnologyView라고 추가 클래스를 만들 수 있습니다 :이 작업을 완료하면

public class TechnologyView 
{ 
    public int Id 
    { 
     get; 
     private set; 
    } 

    public string Name 
    { 
     get; 
     private set; 
    } 

    public string Abbreviation 
    { 
     get; 
     private set; 
    } 

    private TechnologyView() 
    { 
     // Private constructor, required for NH 
    } 

    public TechnologyView(int id, string name, string abbreviation) 
    { 
     this.Id = id; 
     this.Name = name; 
     this.Abbreviation = abbreviation; 
    } 
} 

, 당신은이 클래스의 실존에 대해 NHibernate에 통보해야합니다. 예를 들어, hbm.xml 파일에서 클래스를 가져 오는 방법으로이 작업을 수행 할 수 있습니다. (나는 Fluent를 사용하여 그것을하는 방법을 모른다).

<import class="MyNamespace.TechnologyView" /> 

그 후, 당신은 TechnologyView 인스턴스를 검색 (HQL 또는 기준을 사용하여) 쿼리를 만들 수 있습니다. NHibernate는 현명한 SQL 쿼리를 생성 할만큼 똑똑합니다. HQL을 사용하여

:

IQuery q = s.CreateQuery ("select new TechnologyView (t.Id, t.Name, t.Abbreviation) from Technology t"); 

사용 기준 :

ICriteria criteria = s.CreateCriteria (typeof(Technology)); 
criteria.SetResultTransformer (Transformers.AliasToBean (typeof(TechnologyView)); 
var result = criteria.List<TechnologyView>(); 
+0

이렇게하면 도움이됩니다. 내가 분명히하고 싶은 한 가지는 아마도 잃어버린 길입니다. 내 기술 각각에 대한 TechnologyDescription 테이블의 모든 데이터를 원하지 않는 이유는 설명 중 일부가 내가 속한 페이지와 관련이 없기 때문입니다. 그러나 내가 올바르게 당신을 이해한다면, 나는 기술 실체를 순환하는 방법을 통해 그 결과를 제거하거나 무시하고자 할 것입니다. 이상하게 생각 되긴하지만 그 이후로는 모든 것이 끝나기 때문에 Query 문자열에 대한 이유가 없다는 것을 의미합니다. –

+0

나는 당신의 의견을 정말로 이해하지 못한다. 현재 사용중인 페이지에 대한 설명이 전혀 필요하지 않은 경우 '변환'방식을 선택합니다. –

1

나는 TechnologyDescriptions가로드 게으른을 위해 당신이 찾고있는 것이라고 생각합니다. (NHibernate는 두 번째 db 쿼리를 발행 할 것입니다.) 어떤 상황에서는 N + 1 선택이 가능하고 사용법에 따라 한꺼번에 쿼리를 선호 할 수 있습니다.)

NHibernate xml 매핑은 기본적으로 콜렉션의 지연로드로 매핑됩니다. 과거에는 Fluent NHibernate가 같은 기본값을 가지고 있지 않은 것 같습니다.매핑에 .LazyLoad()을 추가해야합니다. 당신의 양에 Is the default behavior with Fluent NHibernate to lazy load HasMany<T> collections?

관련 문제