2010-12-21 2 views
5

이 작업을 수행하는 데 가장 좋은 방법을 찾는 데 어려움을 겪고 있습니다. 도움을 주시면 감사하겠습니다.Linq-to-SQL : 여러 "포함"필터를 결합 (OR) 하시겠습니까?

기본적으로 사용자가 임의의 "필터"사용자 이름과 관련된 감사 항목의 기록을 볼 수 있도록하는 필터를 설정하고 있습니다.

데이터 원본은 SQL Server 데이터베이스이므로 db 문맥 개체의 직접 테이블 참조 또는 IQueryable을 추가 쿼리에서 가져온 IQueryable "원본"을 취하고 WHERE 필터를 적용합니다. , 그리고 결과로 얻은 IQueryable 객체를 반환하는 것입니다. 그러나이 접근법을 사용하거나 수행하는 방법에 대해서는 다소 혼란 스럽습니다.

표현식의 경로를 사용하는 방법을 알고 있기 때문에 표현식의 경로를 고려해 보았습니다. 그러나 "포함"유형 평가에서이를 수행하는 방법을 이해하지 못했기 때문에 현재 사용하고 있습니다. UNION,하지만이 성능에 부정적인 영향을 미칠 수 있습니다 두려워하고 다른 필터 (여기에 표시된 사용자 이름 필터링 이외에) arbirary 순서로 추가 된 경우 그것이 내게 정확히 무엇을 필요로하지 않을 수 있습니다 궁금하네요. . 여기

내 샘플 코드입니다 :

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source) 
{ 
    // Take allowed values... 
    List<string> searchStrings = new List<string>(); 

    // <SNIP> (This just populates my list of search strings) 

    IQueryable<X> oReturn = null; 

    // Step through each iteration, and perform a 'LIKE %value%' query 
    string[] searchArray = searchStrings.ToArray(); 
    for (int i = 0; i < searchArray.Length; i++) 
    { 
     string value = searchArray[i]; 
     if (i == 0) 
      // For first step, perform direct WHERE 
      oReturn = source.Where(x => x.Username.Contains(value)); 
     else 
      // For additional steps, perform UNION on WHERE 
      oReturn = oReturn.Union(source.Where(x => x.Username.Contains(value))); 
    } 
    return oReturn ?? source; 
} 

이 일을 할 수있는 잘못된 방법 같은 느낌,하지만 내 질문이 할 수있는 더 좋은 방법이있다, 첫째 그래서, 제대로 작동 하는가? 또한 표현식에 '포함'또는 '유사'를 수행 할 수있는 방법이 있습니까?

(편집 해 내 코드를 수정 : 게시하기 위해 작업 상태로 롤백, 나는 분명히 다시 아주 충분히 멀리 롤하지 않았다 :))

========== ===================

주어진 해결책에 따르면, 여기에 내 새로운 코드 (이 읽는 경우 사람에 관심이) :

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source) 
{ 
    List<string> searchStrings = new List<string>(AllowedValues); 

    // <SNIP> build collection of search values 

    string[] searchArray = searchStrings.ToArray(); 

    Expression<Func<X, bool>> expression = PredicateBuilder.False<X>(); 

    for (int i = 0; i < searchArray.Length; i++) 
    { 
     string value = searchArray[i]; 
     expression = expression.Or(x => x.Username.Contains(value)); 
    } 
    return source.Where(expression); 
} 

(한 가지주의 내가 눈치 다음 PredicateBuilder의 예에 따라, 빈 콜렉션 오 f 검색 문자열은 false를 반환합니다 (false || 가치 1 || ...), 원래 버전에서는 필자가 필터링되지 않은 소스에 빈 목록을 연결해야한다고 가정하고있었습니다. 내가 더 생각해봤을 때, 새로운 버전이 내 필요에 더 합당한 것 같다. 그래서 그것을 채택했다.)

==================== ===================================================

+0

LINQ에는 [LIKE] (http://msdn.microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.like.aspx) 메서드가 있습니다 (당신은 의도적으로 포함을 사용하고 있었지만 당신의 의견은 비슷하게 언급되었습니다.) –

+0

왜 검색 문자열 목록을 채우는 블록에서 where 및 union 연산을 수행하지 않습니까? 즉, 'searchStrings.Add (newString)'대신 'result = source.Where (x => x.Username.Contains (newString))'또는'result = result.Union (source.Where (x =>) x.Username.Contains (newString)))'. – phoog

+0

@ 브래드 : 나는 길을 가고 싶었다. 그러나 InvalidOperation (내가 생각하니?) 예외를 어딘가에서 만나기 때문에 내가 무엇을하고 있는지 알지 못했다. – Steven

답변

7

LINQkit의 PredicateBuilder을 사용하여 동적으로 쿼리를 구성 할 수 있습니다.

+0

완벽하게 작동합니다! 고맙습니다 – Steven

관련 문제