2009-05-22 5 views
27

대 다음과 같은 시나리오를 가정 :NHibernate에 - CreateCriteria은 CREATEALIAS

class Project{ 
    public Job Job; 
} 

class Job{ 
    public Name; 
} 

를 내가 그의 작업 이름 "sumthing"가 모든 프로젝트를 검색 할 기준 API를 사용하고자하는 가정.

CreateAlias를 사용하여 Job의 별칭을 만들고 Name에 액세스 할 때 사용할 수 있습니다. 또는 작업 속성에 대한 새 기준을 만들고 이름으로 검색 할 수있었습니다.

성능면에서 현저한 차이가 있습니까? 이러한 요구 사항 주어진

답변

38

하는 것은 차이가 없을 것, 생성 된 SQL은 동일합니다 : 매핑에 대한 :

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="Project" table="Project"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="Id" sql-type="int" not-null="true" unique="true"/> 
      <generator class="native" /> 
     </id> 
     <many-to-one name="Job" column="FK_JobId" cascade="save-update" not-null="true" /> 
    </class> 
</hibernate-mapping> 
<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"> 
    <class name="Job" table="Job"> 
     <id name="Id" type="Int32" unsaved-value="0"> 
      <column name="Id" sql-type="int" not-null="true" unique="true"/> 
      <generator class="native" /> 
     </id> 
     <property name="Name" type="String"> 
      <column name="Name" sql-type="nvarchar" length="50" not-null="true"/> 
     </property> 
    </class> 
</hibernate-mapping> 

와 클래스

public class Project 
    { 
     public Project() { } 

     public virtual int Id { get; set; } 

     public virtual Job Job { get; set; } 
    } 
public class Job 
    { 
     public Job() { } 

     public virtual int Id { get; set; } 

     public virtual String Name { get; set; } 
    } 

이 기준은

ICriteria criteriacrit = session 
    .CreateCriteria(typeof (Project)) 
    .CreateCriteria("Job", "job") 
    .Add(Restrictions.Eq("job.Name", "sometextA")); 

ICriteria aliascrit = session 
    .CreateCriteria(typeof (Project)) 
    .CreateAlias("Job", "job") 
    .Add(Restrictions.Eq("job.Name", "sometextB")); 

을있는 정의 동일한 SQL을 생성

SELECT 
    this_.Id as Id2_1_, 
    this_.FK_JobId as FK2_2_1_, 
    job1_.Id as Id1_0_, 
    job1_.Name as Name1_0_ 
FROM 
    Project this_ 
    inner join Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextA' 

SELECT 
    this_.Id as Id2_1_, 
    this_.FK_JobId as FK2_2_1_, 
    job1_.Id as Id1_0_, 
    job1_.Name as Name1_0_ 
FROM 
    Project this_ 
    inner join Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextB' 

노트는 그러나 CreateAliasCreateCriteria 호출이 JoinType을 지정할 수 있습니다 반면 연결을 생성하기 위해 매핑에 의존하고있다.

차이 createCriteria

로 구성 새로운 기준을 반환) createCriteria을 (결과로

때문에, 이러한 호출은

ICriteria criteriacrit = session 
    .CreateCriteria(typeof(Project)) 
    .CreateCriteria("Job",JoinType.LeftOuterJoin) 
    .Add(Restrictions.Eq("Name", "sometextA")); 

ICriteria aliascrit = session 
    .CreateCriteria(typeof (Project)) 
    .CreateAlias("Job", "job") 
    .Add(Restrictions.Eq("job.Name", "sometextB")); 

는 원래의 기준을 반환) (

SELECT 
    this_.Id as Id2_1_, 
    this_.FK_JobId as FK2_2_1_, 
    job1_.Id as Id1_0_, 
    job1_.Name as Name1_0_ 
FROM 
    Project this_ 
    **left outer** join Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextA' 

SELECT 
    this_.Id as Id2_1_, 
    this_.FK_JobId as FK2_2_1_, 
    job1_.Id as Id1_0_, 
    job1_.Name as Name1_0_ 
FROM Project this_ 
    **inner join** Job job1_ 
    on this_.FK_JobId=job1_.Id 
WHERE job1_.Name = @p0; @p0 = 'sometextB' 
+1

그러나 CreateAlias ​​오버로드에서 조인 유형을 지정할 수 있습니까? CreateAlias는 항상 내게 내부 조인으로 기본 설정되어있는 것처럼 보입니다. many-to-one이 null을 허용하는 경우에도 마찬가지입니다. – dotjoe

+4

예 NH2 ++에서는 CreateAlias를 사용하여 매핑 된 연결을 재정의하는 JoinType을 지정할 수 있습니다. 생성 된 ICriteria 여러 방법으로 조작 할 수 있기 때문에 CreateCriteria (연결된 엔터티에 "뿌리") ICriteria 개체를 반환하기 때문에 다른 (고급) 쿼리를 생성 할 수 있습니다 같아요. – Jaguar

7

CREATEALIAS 이러한 SQL 문을 생성 예를 들어 체인 방법 일 때

cr.createAlias ​​(). (Restrictions.ilike ("code", "abc"))는 엔터티에 대한 제한을 추가합니다. cr.createCriteria ("parent", "p"). add (Restrictions.ilike "code", "abc"))은 부모에게 제한을 더한다.

22

NHibernate 2.0에서 CreateCriteria와 CreateAlias의 차이점을 설명하기 위해 다음 도메인 모델을 볼 수있다. 내부는 처음 CreateCriteria가 실행될 때 "분류"개체를 반환하기 때문에

var criteria = DetachedCriteria.For<Product>() 
       .CreateCriteria("Category", JoinType.InnerJoin) 
       .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin) 
       .Add(Restrictions.Le("ps.Stock",10)); 

위의 기준은 일을 못해 이들 기관에 가입하려면 지금

public class Product 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Name { get; set; } 
    public virtual decimal Price { get; set; } 
    public virtual Category Category { get; set; } 
    public virtual IList<ProductStock> ProductStocks { get; set; } 
} 

public class Category 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Name { get; set; } 
    public virtual IList<Product> Products { get; set; } 
} 

public class ProductStock 
{ 
    public virtual int Id { get; private set; } 
    public virtual Product Product { get; set; } 
    public virtual string WarehouseName { get; set; } 
    public virtual int Stock { get; set; } 
} 

당신은 두 번째 CreateCriteria 그것을 실행 때문에 때, 다음과 같은 기준을 작성하는 경우 "Category"엔티티에서 ProductStocks 속성을 찾지 못하면 쿼리가 실패합니다.첫 번째 CREATEALIAS 두 번째 CreateCriteria 그것이 "제품"엔티티에 속성 ProductStocks를 찾을 실행할 때, "제품"개체를 반환 실행하면

그래서이 기준을 작성하는 올바른 방법은

var criteria = DetachedCriteria.For<Product>() 
       .CreateAlias("Category", "c", JoinType.InnerJoin) 
       .CreateCriteria("ProductStocks", "ps", JoinType.InnerJoin) 
       .Add(Restrictions.Le("ps.Stock",10)); 

입니다.

그래서 TSQL은 이렇게됩니다.

SELECT this_.ProductID  as ProductID8_2_, 
     this_.Name   as Name8_2_, 
     this_.Price   as Price8_2_, 
     this_.CategoryID as CategoryID8_2_, 
     ps2_.ProductStockID as ProductS1_9_0_, 
     ps2_.Stock   as Stock9_0_, 
     ps2_.ProductID  as ProductID9_0_, 
     ps2_.WarehouseID as Warehous4_9_0_, 
     c1_.CategoryID  as CategoryID0_1_, 
     c1_.Name   as Name0_1_ 
FROM [Product] this_ 
     inner join [ProductStock] ps2_ on this_.ProductID = ps2_.ProductID 
     inner join [Category] c1_ on this_.CategoryID = c1_.CategoryID 
WHERE ps2_.Stock <= 10 

이 정보가 도움이되기를 바랍니다.

+0

이것은 많은 의미가 있으며 원래의 질문에 답합니다. – Oliver