2012-03-20 4 views
0

내가 (동등한 효과 나)이에 SQL과 유사한 초래 criteria 질의를 작성하는 방법의 예를 찾고 있어요 : 만들 때NHibernate에 기준 쿼리 - 방법 체인 논리 연산자

SELECT x, y, z 
FROM SomeTable tbl 
WHERE tbl.a = 'some value' 
    AND (
    (tbl.b = '1' AND tbl.c = 'whatever1' AND tbl.d = 123) OR 
    (tbl.b = '2' AND tbl.c = 'whatever2' AND tbl.d = 456) OR 
    (tbl.b = '3' AND tbl.c = 'whatever3' AND tbl.d = 789) 
) 

쿼리는 필터 데이터 목록 ("AND"다음에 오는 데이터를 채 웁니다)과 추가 매개 변수 (위의 '일부 값'부분을 채 웁니다)가 있습니다.

기본적으로 내 질문은 이런 종류의 기준 쿼리를 작성할 때 AND 및 OR을 연결하는 방법입니까? Expression.And 및 Expression.Or에 대한 API는 체인이 아닌 단일 왼쪽 및 오른쪽 기준 만 허용합니다.

누구든지이 예제를 어디에서 찾을 수 있습니까?

지금까지 (xw, y, z) 부분은 현재 관련이 없으므로 투영으로 달성 할 수 있습니다 (아직받지 못했습니다).

답변

1

논리 연산자 체인과 같은 것은 없습니다. 위의 내용은 다음과 같이 쓸 수도 있습니다

(tbl.b = '1' AND tbl.c = 'whatever1' AND tbl.d = 123) OR 
    ((tbl.b = '2' AND tbl.c = 'whatever2' AND tbl.d = 456) OR 
    (tbl.b = '3' AND tbl.c = 'whatever3' AND tbl.d = 789)) 

즉, 논리 연산자에는 항상 왼쪽 및 오른쪽 매개 변수가 있습니다. 말했다

는 비트 연산자는 Restriction 과부하, 그렇게되는 다음 작품 : 기준의 API는 접속사를 사용 (AND) 할 수 있으며 분리 (OR) 클래스와

criteria.Add(Restrictions.Eq("a", "some value") & 
      (Restrictions.Eq("b", 1) & Restrictions.Eq("c", "whatever1") | 
      (Restrictions.Eq("b", 2) & Restrictions.Eq("c", "whatever2")))) 
      //...etc... 
+0

멋집니다! 나는 그것을 시도 할 것입니다 ... – joniba

+0

사실은 처음 시도가 실제로 효과가 있었으므로 결국 시도하지 않았고 그것을 바꾸고 싶지 않습니다. 그러나 이것이 우아한 해결책처럼 보이기 때문에 이것을 답으로 표시 할 것입니다. 나는 내 대답을 별도로 게시 할 것이다. – joniba

1

. 예를 들어, this stackoverflow thread

+0

그래서 Conjunction() 이후에 원하는만큼 많은 제한/표현식을 추가 할 수 있으며 add/or? 아니면 그 모범을 이해하지 못했습니까? – joniba

+0

기본적으로 예입니다. 연결자는 숫자 제한을 받아 논리적 AND로 연결합니다. 분리 (Disjunction)는 여러 가지 제한을 받지만 OR로 연결합니다. 또한 결합 안에 분리를 포함 할 수도 있고 그 반대의 경우에도 분리를 포함 할 수 있습니다. –

0

글쎄, 내 초기 시도가 실제로 효과가있는 것처럼 보입니다. 그래서 누군가에게 관심이있는 경우에 대비해 내가 어떻게했는지 게시 할 것입니다.

public IEnumerable<Entity> Filter(FilterRequest filterRequest) 
    { 
     var criteria = session.CreateCriteria("Entity"); 

     criteria.Add(
      Expression.And(
       CreateItemCriteria(filterRequest), 
       CreateKeysCriteria(filterRequest))); 

     return criteria.List<Entity>(); 
    } 

    private static ICriterion CreateItemCriteria(FilterRequest filterRequest) 
    { 
     return Restrictions.Eq("a", filterRequest.ItemId); 
    } 

    private ICriterion CreateKeysCriteria(FilterRequest filterRequest) 
    { 
     ICriterion finalCriterion = null; 

     for (int i = 0; i < filterRequest.Keys.Count; i++) 
     { 
      var currentKeyCriterion = CreateKeyCriterion(filterRequest.Keys[i]); 

      finalCriterion = finalCriterion == null 
       ? currentKeyCriterion 
       : Expression.Or(finalCriterion, currentKeyCriterion); 
     } 

     return finalCriterion; 
    } 

    private ICriterion CreateKeyCriterion(Key key) 
    { 
     return Expression.AllEq(new Dictionary<string, object> 
      { 
       { "b", Key.b }, 
       { "c", Key.c }, 
       { "d", Key.d }, 
      }); 
    } 

매우 우아하지는 않지만 작동하며 결과 SQL은 원했던 그대로입니다.