2014-12-18 3 views
3

쿼리를 실행하고 Linq에서 엔터티 쿼리에이 필터를 기반으로 결과를 반환해야하는 CustomerFilter 개체의 배열을 통해 응용 프로그램에 전달되는 필터 조건이 있다고 가정 해보십시오.여러 수준 where 절을 Linq로 필터링

그래서이 경우 고객은 나를 서비스 호출을 통해 CustomerFilter 객체의 배열로 전달하게됩니다.

필터 개체 :

class CustomerFilter 
{ 
    public string CustomerID; 
    public int[] LocationID; 
} 

예 데이터 :

CustomerID LocationID 

1    1 

       2 

       3 

       4 

2    2 

       3 


       4 

내가 다음과 같이 아주 쉽게 외부의 CustomerID에 대한 쿼리 필터링을 구축 할 수 있습니다.

검색어 :

public void GetCustomerResults(List<CustomerFilter> accounts) 
    { 
     List<string> customer = (from a in accounts select a.CustomerID).ToList(); 

     var locations = ctx.Portal_SurveyLocations 
          .Where(w => customer.Contains(w.CustNum)) 
          .OrderBy(o => o.LocationKey); 
    } 

그래서 내가 외부 기준으로 필터링 할 수 있지만 각 CustomerID를위한 여러 위치 ID를 기준으로 필터링하는 방법을 잘 모르겠습니다. 분명히 OR 절을 넣으면 위치 ID가 일치하는 다른 CustomerID를 가져 오므로 잘못된 결과가 나타납니다.

CustomerFilter 객체가 전달되면이 다중 레벨 필터를 수행하는 방법에 대한 아이디어가 있습니까?

답변

5

약간의 재 작업. 기본적으로 우리는 Any의 조합을 사용하여 원하는 결과를 얻기 위해 하위 모음을 탐색합니다. 빠른 검색을 위해

var locations = ctx.Portal_SurveyLocations 
    .Where(w => accounts.Any(a => a.CustomerID == w.CustNum && 
            a.LocationID.Any(l => w.LocationKey == l))) 
    .OrderBy(o => o.LocationKey); 
+0

LocationID.Any에있는 lamba 표현식의 범위 문제로 인해 컴파일되지 않습니다. 'w'라는 로컬 변수는이 범위에서 선언 할 수 없습니다. 왜냐하면 ' w '는 이미 무언가를 나타 내기 위해'부모 또는 현재 '범위에 사용됩니다. –

+2

@mattytommo 두 가지 다른 범위에서'w' 변수를 사용하려고 했으므로 코드를 조정했습니다 :'Where' lambda와'a.LocationID.Any'도 포함되어 있으므로 @ PhilMurray의 컴파일러 오류가 발생했습니다. 나는 이것이 문제를 해결해야한다고 생각한다. – IronMan84

+1

@ IronMan84 토니 스탁 (Tony Stark), 고마워, 고마워. – mattytommo

0

당신이 필터 객체에서 해시 세트의 사전을 만들 수 있습니다 (A ListContains를 사용하여 매우 빠르게 아니다).

사전에는 각 고객에 대해 하나의 항목이 포함되며 해당 항목의 값은 위치의 해시 세트가됩니다.

public void GetCustomerResults(List<CustomerFilter> accounts) { 
    Dictionary<string, HashSet<int>> lookup = 
    accounts.ToDictionary(a => a.CustomerID, a => new HashSet<int>(a.LocationID)); 

    var locations = 
     ctx.Portal_SurveyLocations 
     .Where(w => 
     lookup.ContainsKey(w.CustNum) && 
     lookup[w.CustNum].Contains(w.LocationKey)) 
     .OrderBy(o => o.LocationKey); 
} 

찾고에 대한 사전 및 해시 세트 모두가 O(1) 복잡성을 가지고 그것을 사용하면 고객이 사전에있는 경우, 먼저는 위치가 해당 고객의 해시 세트에있는 경우 다음 확인, 확인 전체 작업이 O(n+m)의 복잡도를 가지므로 n은 필터 수이고 mPortal_SurveyLocations의 항목 수입니다.

+2

이지도를 Linq에 직접 매핑 하시겠습니까? – mattytommo

관련 문제