2014-06-11 4 views
1

필드가 회사 이름을 말하고 사용자가 입력 한 데이터를 부분적으로 공백으로 구분하여 검색하려고합니다. 사용자가 'ABC India PVT Ltd' 을 입력한다고하면 입력 한 단어가 하나 이상 포함 된 모든 레코드를 검색해야합니다. SQL처럼 내가 어떤이Linq에서 공간 분리 값에 대한 부분 검색

string search = "ABC India PVT Ltd" 
String[] searchArray = search.Split(' '); 
IEnumerable<Account> accountInfo = acctInfo.Get(Filter: a 
=>searchArray.AsQueryable().Contains(a.CompanyName)); 

처럼 뭔가를 시도하고

Select * 
from Company 
where CompanyName like '%ABC%' or 
     CompanyName like '%India%' or 
     CompanyName like '%PVT%' or 
     CompanyName like '%Ltd%' 

것입니다 그러나 이것은 나에게 내가 달성하기 위해 노력하고 무엇 정반대을 제공합니다. 나는 이것을 달성 할 수있는 방법이 있나.

기본 아이디어는 모든 searchArray 값에 대해 회사 이름 필드 와일드 카드 검색입니다.

a.CompanyName.Contains ('searchArray에서 모든 값')

답변

1

이 트릭을 수행합니다.

string searchTerm = "ABC India PVT Ltd"; 
string[] keywords = searchTerm.Split(' '); 

List<Records> records = new List<Records>(); 
records.Add(new Records() { CompanyName = "Foo name" }); 
records.Add(new Records() { CompanyName = "ABC name" }); 
records.Add(new Records() { CompanyName = "Foo India" }); 
records.Add(new Records() { CompanyName = "PVT name" }); 
records.Add(new Records() { CompanyName = "Foo name" }); 
records.Add(new Records() { CompanyName = "Foobar" }); 
records.Add(new Records() { CompanyName = "Stackoverflow" }); 

var results = records.Where(x => keywords.Any(keyword => x.CompanyName 
             .Contains(keyword))).ToList(); 

더미 클래스 :

public class Records 
{ 
    public Records() { } 
    public string CompanyName { get; set; } 
} 

당신에게 CompanyName 키워드 중 하나를 포함 레코드 List<Record>을 줄 것이다 키워드 중 하나를 포함하는 레코드를 필터링 할 Any()를 사용합니다.

  • "푸 인도"
  • "PVT 이름"예

    • "ABC 이름"
  • 1

    DGibbs 제안한 Any있는 솔루션 요소의 작은 숫자 OK입니다 (이 아마 것 당신을위한 경우, 그래서 나는 upvoted)하지만 EF는이 구조에서 효율적인 쿼리를 구축 할 수 없습니다. 이 쿼리가 4 요소 모습입니다 :

    SELECT 
    -- some fields 
    FROM [dbo].[Company] AS [Extent1] 
    WHERE EXISTS (SELECT 
        1 AS [C1] 
        FROM (SELECT 
         [UnionAll2].[C1] AS [C1] 
         FROM (SELECT 
          [UnionAll1].[C1] AS [C1] 
          FROM (SELECT 
           N'a' AS [C1] 
           FROM (SELECT 1 AS X) AS [SingleRowTable1] 
          UNION ALL 
           SELECT 
           N'b' AS [C1] 
           FROM (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1] 
         UNION ALL 
          SELECT 
          N'c' AS [C1] 
          FROM (SELECT 1 AS X) AS [SingleRowTable3]) AS [UnionAll2] 
        UNION ALL 
         SELECT 
         N'd' AS [C1] 
         FROM (SELECT 1 AS X) AS [SingleRowTable4]) AS [UnionAll3] 
        WHERE (CAST(CHARINDEX([UnionAll3].[C1], [Extent1].[Name]) AS int)) > 0 
    ) 
    

    이 확장되지 않습니다. 특정 수의 요소 (수십 개)를 초과하면 쿼리는 최대 중첩 수준이 초과 된 SQL 예외를 throw합니다.

    이 문제를 방지하려면 OR 절을 사용하여 쿼리를 작성해야합니다. 이 PredicateBuilder 도움이 될 곳이다 :

    var predicate = PredicateBuilder.False<Company>(); 
    
    foreach (var keyword in searchArray) 
    { 
        predicate = predicate.Or(c => c.Name.Contains(keyword)); 
    } 
    
    var query = Companies.Where(predicate.Expand()); 
    

    있다, 그런데, 같은 않지만, Expand없이 LINQKit의 PredicateBuilder,에 source-code alternative.

    +0

    답장을 보내 주셔서 감사합니다. – shiv

    관련 문제