2009-03-01 3 views
4

검색을 수행하기 위해 nHibernate 조건식을 빌드하려고합니다.nHibernate의 조인에 대한 필터

주어진 다음의 데이터 모델 :

  • 동작은 0 개 이상의 세션을 가질 수있다.
  • 더 많은 작업 유형이 일 수 있습니다.

나는 다음과 같은 기준에 따라 모든 세션을 검색하려면 : 작업 이 isActive 플래그가 true 인 경우

  • (필수), ( 플래그

오 사실이다 IsPublished 선택적으로) 및 작업 상태/종료 날짜가 사용자가 지정한 날짜 범위 내에있는 경우

(선택 사항) regionid 사용자 지정된 ID

(임의로) O 세션 부문 (선택적으로) 사용자가 지정한 ID

O 일치와 일치 Operation.OperationTypes 타입 ID의 사용자 지정리스트 어디

(모든 선택적 매개 변수를 제공 한 부여)로

나는 SQL이를 표현하는 것입니다 :

SELECT  
    [Session].* 
FROM   
    [OperationTypeOperation] 
LEFT OUTER JOIN 
    [Operation] ON [OperationTypeOperation].[OperationId] = [Operation].[OperationId] 
RIGHT OUTER JOIN 
    [Session] ON [Operation].[OperationId] = [Session].[OperationId] 
WHERE 
    ([Operation].[IsPublished] = 1) 
AND 
    ([Operation].[IsActive] = 1) 
AND 
    ([Session].[RegionId] = 66) 
AND 
    ([Session].[DivisionId] = 99) 
AND 
    ([Operation].[AdvertisingStartDate] < GETDATE()) 
AND 
    ([Operation].[AdvertisingEndDate] > GETDATE()) 
AND 
    ([OperationTypeOperation].[OperationTypeId] IN (1, 2, 3)) 

그리고 같은 내 nHibernate 수 쿼리 :

public PagedResult<Session> Search(int? regionId, int? divisionId, DateTime? startDate, DateTime? endDate, IList<int> operationTypeId, int itemsPerPage, int page) 
     { 

      var criteria = _session.CreateCriteria(typeof(Session)) 
       .Add(Expression.Eq("IsActive", true)) 
       .Add(Expression.Eq("AcceptingApplications", true)) 
       .AddOrder(new Order("StartDate", false)) 
       ; 

      if (regionId.HasValue) 
       criteria.Add(Expression.Eq("Region.Id", regionId.Value)); 

      if (divisionId.HasValue) 
       criteria.Add(Expression.Eq("Division.Id", divisionId.Value)); 

      if (startDate.HasValue) 
       criteria.Add(Expression.Ge("StartDate", startDate.Value)); 

      if (endDate.HasValue) 
       criteria.Add(Expression.Le("EndDate", endDate.Value)); 

      //Add the operation types 
      if (operationTypeId.Count > 0) 
      { 
       var operationTypes = new Collection<OperationType>(); 
       foreach (int id in operationTypeId) 
       { 
        operationTypes.Add(_session.Get<OperationType>(id)); 
       } 
       //Join on the operations 
       criteria.CreateCriteria("Operation") 
       .Add(Expression.Eq("IsPublished", true)) 
       .Add(Expression.Eq("IsActive", true)) 
       .Add(Expression.Le("AdvertisingStartDate", DateTime.Now)) 
       .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now)) 
       .CreateAlias("OperationTypes", "operationTypes", JoinType.InnerJoin) 
       .Add(Expression.In("OperationTypes", operationTypes)) 
       .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
       ; 
      } 
      else 
      { 
       //Join on the operations 
       criteria.CreateCriteria("Operation") 
       .Add(Expression.Eq("IsPublished", true)) 
       .Add(Expression.Eq("IsActive", true)) 
       .Add(Expression.Le("AdvertisingStartDate", DateTime.Now)) 
       .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now)) 
       ; 
      } 

      return criteria.ToPagedResult<Session>(itemsPerPage, page); 
     } 

내 nHibernate 함수가 작업 유형에 대해 불평하고 "InExpression과 함께 콜렉션을 사용할 수 없습니다"라는 예외를 던지고 있습니다. 게다가 조인 된 테이블을 올바르게 필터링하고 있는지 확실하지 않습니다. 누구나 nHibernate 표현식으로 위의 SQL을 작성하는 올바른 방법으로 무게가나요?

답변

5

나는 OperationType이 엔티티 클래스 (enum이 아님)라고 가정합니다. 엔티티 목록에는 In을 사용할 수 없습니다. ID를 사용하여 가입 할 수 있습니다.

criteria 
    .CreateCriteria("Operation") 
    // add other expressions 
    .CreateCriteria("OperationTypes", "operationTypes", JoinType.LeftOuterJoin) 
    .Add(Expression.In("operationTypes.Id", operationTypeId)) 

나는 _session.Get (id)가 데이터베이스 쿼리를 수행한다고 가정합니다. 어쨌든 이것을 피하십시오.

추 신 : OperationType이 복합 컬렉션 (<composite-element> 태그 포함)으로 매핑되는 경우 불행히도 조건과 조인 할 수 없습니다. 해결 방법이 있는지 확실하지 않습니다. 패치 보류 중입니다.

1

내가 쓰는 것보다 더 좋은 방법이 생각 : 추가가 "Operation"

수행 조인 때문에

criteria 
    .CreateCriteria("Operation") 
    // add other expressions 
    .CreateCriteria("OperationTypes", "operationTypes", JoinType.LeftOuterJoin) 
    .Add(Expression.In("operationTypes.Id", operationTypeId)) 

당신은 간단하게 작성할 수 있습니다

criteria.Add(Expression.In("OperationTypes", operationTypeId)) 
.CreateCriteria("Operation") 
         .Add(Expression.Eq("IsPublished", true)) 
         .Add(Expression.Eq("IsActive", true)) 
         .Add(Expression.Le("AdvertisingStartDate", DateTime.Now)) 
         .Add(Expression.Ge("AdvertisingEndDate", DateTime.Now)) 
         .SetResultTransformer(new DistinctRootEntityResultTransformer()) 
관련 문제