0

NHibernate 구현 및 지연로드 사용 프로젝트가 있습니다. 이 프로젝트에는 Person 클래스와 PersonIdentity 클래스가 있습니다. 그 둘 사이의 관계는 집합체이며, 사람이 한 PersonIdentity를 가졌다는 것을 의미합니다.NHibernate 쿼리 및 최상의 성능 최적화 방법

사람 매핑은 다음과 같습니다

<class name="Person" table="Person_Person" > 

    <id name="Id" type="Int64" unsaved-value="0"> 
     <generator class="native" /> 
    </id> 

    <version name="Version" /> 

    <property name="Name" column="Name" 
       type="String(255)" access="property" not-null="false" /> 

    <one-to-one name="Identity" property-ref="Person" 
     class="Domain.Entities.PersonIdentity,Domain.Entities" cascade="delete" fetch="select" /> 

</class> 

PersonIdentity 매핑은 다음과 같습니다

<id name="Id" type="Int64" unsaved-value="0" > 
     <generator class="native" /> 
    </id> 

    <property name="FirstName" column="FirstName" type="String(255)" access="property" not-null="false" /> 

    <property name="LastName" column="LastName" type="String(255)" access="property" not-null="false" /> 

    <many-to-one name="Person" column="Person_id_fk" uniqe="true" class="Domain.Entities.Person,Domain.Entities" 
     outer-join="auto" fetch="select" access="property" not-null="true" /> 

    </class> 

내 문제는 성능이다. 이 같은 유일한 사람에 쿼리를 실행하면 :

SELECT * FROM Person_Identiyt WHERE Id = 1; 
SELECT * FROM Person_Identiyt WHERE Id = 2; 
SELECT * FROM Person_Identiyt WHERE Id = 3; 
... 
:

var q = SessionInstance.Query<Person>(); 
IList list = q.ToList<Person>(); 

을 난 단지, 데이터베이스 인당

SELECT * FROM Person_Person 

그러나 추가를 실행과 같은 쿼리를 실행 기대

그리고 게으른 접근 방식에 따르면 좋지 않습니다. PersonIdentity는 호출하기 전에로드해야합니다. 맨 처음로드 할 때 PersonIdentity가없는 Person 만로드 할 수 있습니까?

+0

항상 사람 – Ehsan

답변

1

프록시 (lazy-loading)는 선택적인 일대일 사용자에게는 절대 사용되지 않습니다.

프록시는 항상 무언가 있음을 의미하지만 일대일의 경우 다른 테이블에 행이 존재하지 않을 수도 있습니다. 프록시가 소유자 속성에서 자체를 제거하고 (null로 설정하는) 프록시가 사용할 수 없으므로 프록시를 사용할 수 없습니다.

DB가 항상 신원 (신원에서 신원까지의 외래 키)이 있는지 확인하는 경우 constrained="true"을 일대일로 추가 할 수 있으며 NHibernate는 프록시를 사용합니다.

해결 방법 :

  • 항상 선택 N + 1 문제를 방지하기 위해 (fetch="join" 포함) 신원을로드합니다. (참고 : 정확하게 기억한다면 버그가있을 수 있으므로 NHibernate Jira를 참조하십시오.)
  • 참조를 컬렉션으로 매핑하고 Person 클래스에서 collection.SingleOrDefault()을 호출하는 속성을 제공하십시오. 그렇게하면 게으른 로딩을 사용할 수 있습니다.
+0

에 대한 신원가 내가 추가 한 '제약 = "true"로'사람의 HBM에서 PersonIdentity에 대한 일대일 관계로. 그러나 두 가지 문제가 있습니다. * insert * 및 * delete * Person이이 메시지로 오류가있을 때 : not-null 속성은 null 또는 일시적인 값을 참조합니다. Domain.Entities.PersonIdentity.Person. 그러나 업데이트는 사실입니다. 왜? – Ehsan

+0

왜이 변경으로 인해 Domain.Entities.PersonIdentity.Person이 일시적입니까? 그러나'constrained = "true"를 추가하기 전에 그것은 옳았습니까? Person에 대한 GetByID (x)'가 여전히 각각의 경우에 존재할 때 또한'Select * from Person_Person'은'Select * from Person_identity where ID = x'에 대한 두 번째 쿼리를 실행했습니다. 왜? – Ehsan

+0

@ehsanzeynali'PersonIdentity'와 엔티티를 저장하고 불러오는 데 사용하는 코드의 매핑을 게시하십시오. – cremor