2009-02-28 8 views
11

검색 상자에 입력 한 키워드를 기반으로 검색해야하는 코스 테이블이 있습니다. LINQ 동적으로 각 키워드를 기반으로 WHERE 문을 생성 할 경우 LINQ multiple where 절

SELECT * FROM Courses WHERE 
Title LIKE '%word%' OR Title LIKE '%excel%' OR 
Contents LIKE '%word%' OR Contents LIKE '%excel%' 

가 어떻게 LINQ이를 변환 할 수 있습니다 다음은 샘플 쿼리입니다.

필드가 VARCHAR 인 한 PredicateBuilder를 사용해 보았습니다. "TEXT"필드의 경우 따옴표가 생성되지 않으므로 컴파일러가 오류 메시지를 표시합니다. 여기 PredicateBuilder

SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active], 
FROM [dbo].[Courses] AS [t0] 
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR 
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%) 

주의에 의해 생성 된 SQL은 데이터베이스에 텍스트 필드 인 "내용"필드에 대한 단일 견적이없는 것입니다.

WHERE 구문을 작성하고 쿼리를 첨부하는 쉬운 방법이 있습니까? 누구든지 내가 PredicateBuilder없이 어떻게 할 수 있는지 알고 있니?

미리 감사드립니다.

답변

13

LINQ로 작업하고 있으므로 LINQ-to-SQL 데이터 컨텍스트에 맞춰 작업하고 있다고 생각하십니까? 이 문제를 테스트하기 위해 여분의 DataContext가 없지만 몇 가지 아이디어가 있어야합니다.

데이터 컨텍스트에 대해 작동하는지는 잘 모르겠지만 대부분이 쿼리가 SQL로 변환 될 때 문제를 일으키지 않아야하는 매우 기본적인 것들 (체인 OR 연산자 및 포함 된 메서드 호출)입니다.

Func<string, Func<DataItem, bool>> buildKeywordPredicate = 
    keyword => 
     x => x.Title.Contains(keyword) 
      || x.Contents.Contains(keyword); 

이 하나의 문자열 키워드를 소요 한 후있는 DataItem 소요 키워드에 대해 그것을 확인 다른 함수를 반환하는 기능은 다음과 같습니다

먼저 내 술어를 구축 할 사용자 정의 함수를 만듭니다.

기본적으로 "스택"을 전달하면 조건부 : x => x.Title.Contains("Stack") || x.Contents.Contains("Stack")이 표시됩니다.

가 여러 가지 키워드는 당신이 OR 연산과 체인이 필요하기 때문에 다음, 내가 OR

이 기능은 2 술어를 취
Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate = 
    (pred1, pred2) => 
     x => pred1(x) || pred2(x); 

다음으로 2 술어 함께 체인에 또 다른 도우미 함수를 만들

그것들을 OR 작업과 결합하십시오.

그 두 기능을 갖는, 그때 구축 할 수 있습니다 내 경우 같은 조건 :

foreach (var word in keywords) {    
    filter = filter == null 
     ? buildKeywordPredicate(word) 
     : buildOrPredicate(filter, buildKeywordPredicate(word)); 
} 

필터가 null의 경우 루프 내부의 첫 번째 줄은 기본적으로 확인합니다. 그렇다면 간단한 키워드 필터가 필요합니다.

필터가 null이 아닌 경우 기존 필터를 OR 연산으로 연결해야하므로 기존 필터와 새 키워드 필터를 buildOrPredicate에 전달하여이를 수행합니다.

그리고 우리는 지금 쿼리의 WHERE 부분 만들 수 있습니다

var result = data.Where(filter); 

우리가 구축 한 복잡한 조건에 전달합니다.

이것이 PredicateBuilder 사용과 다른지는 모르겠지만 LINQ-to-SQL 엔진으로 쿼리 변환을 연기하기 때문에 아무런 문제가 없어야합니다.

하지만 내가 말했듯이 실제 데이터 컨텍스트와 비교하여 테스트하지 않았으므로 문제가있는 경우 주석에 쓸 수 있습니다. 이 도움이 http://pastebin.com/feb8cc1e

희망 :

는 여기에 내가 시험에 내장 된 콘솔 응용 프로그램입니다!


편집 : 제대로 LINQ에 식 나무를 활용 포함하는 더 일반적인 재사용 가능한 버전에 대한은 토마스 Petricek의 블로그 게시물을 체크 아웃 : http://tomasp.net/articles/dynamic-linq-queries.aspx

+1

이 unfortunatelly 기능에만 작동합니다. Expression Trees로이 작업을하려면 다음과 같은 트릭을 사용해야합니다. http://tomasp.net/articles/dynamic-linq-queries.aspx –

+0

그게 바로 당신이 해낸 위업입니다! 더 awesomeness ... 어쨌든, 난 지금 귀하의 블로그 구독자입니다 :-) – chakrit

+0

고마워,이 하나의 일했습니다. http://tomasp.net/articles/dynamic-linq-queries.aspx - Tomas Petricek – Amir

0

프리디 케이트 빌더는 Contains 메소드가 호출 된 속성의 DB 유형을 알지 못하기 때문에 SQL에서 linq 내부의 문제 일 수 있습니다. 당신은 일반적인 쿼리 (predicate builder가 아닌)와 Contains가있는 TEXT 컬럼으로 시도해 봤습니까?