2009-11-05 2 views
1

나는 이상하고 특이한 방식으로 필터링하려고하는 LINQ 결과 세트가 있습니다.문자열 목록에서 하위 문자열을 선택/필터링하는 방법은 무엇입니까?

List<string> MyDomains = [Code to get list]; 

var x = (from a in dc.Activities 
    where a.Referrer != null 
     && a.Referrer.Trim().Length > 0 
     && !a.Referrer.Contains("localhost") 
     && a.SearchResults.Count() == 0 
    orderby a.ID descending 
    select a) 
    .Take(20); 

이제는 설명이 잘못되었습니다. 더 잘 설명해 드리겠습니다. MyDomains는 문자열 목록입니다. 각각은 내가 소유 한 루트 도메인입니다.

a.Referrer는 GET에서 내 웹 사이트 중 하나에 대한 리퍼러가 포함 된 문자열입니다. 이 문자열에는 하위 도메인, 폴더, 파일 및 쿼리 문자열이 포함됩니다.

MyDomains 목록에있는 a.Referrer의 루트 도메인으로 x를 필터링하려고합니다. 즉,이 방식으로 일치하지 않는 모든 레코드를 반환하고 싶습니다. 결과 집합은 추천자가 내 도메인이 아닌 활동을 포함하게됩니다.

나는 람다 표현식을 배웠지 만, 지금까지 논리를 가진 where 절 (사실상 루프, 하위 문자열 등)이 필요하기 때문에 지금까지이 목표를 달성 할 수 없었습니다.

현재 X를 목록에 캐스팅하고 수동으로 필터링 한 다음 X를 바인딩하는 대신 대상 컨트롤에 바인딩합니다. 확장 방법이있어 Uri의 루트 도메인을 가져오고 그것이 내 도메인이든 아니든, "SQL로 지원되는 변환이 없으므로"여기에 람다를 넣을 수는 없습니다.

구조적 차이 이외에도 LINQ 쿼리에서이 문제를 어떻게 해결할 수 있습니까?


참고 : 내 .Take (20)가 추가되기 전에 일치하는 레코드를 제거 할 수 있도록 쿼리 내에서이 작업을 수행하려고합니다. 나는 더 많은 데이터베이스를 호출 할 필요없이 매번 같은 수의 결과를 얻고 싶습니다. 내가 이해하면

답변

1

을해야한다고 생각 MyDomains의 항목을 부분 문자열로 사용합니다.

다음, 또는 이와 유사한 작동한다 :

var theActivities = (from a in dc.Activities 
    where a.Referrer != null 
     && a.Referrer.Trim().Length > 0 
     && a.SearchResults.Count() == 0 
    select a); 

foreach(var domain in MyDomains) { 
    theActivities = theActivities.Except(dc.Activities.Where(a => a.Referrer.Contains(domain))); 
} 

theActivities = theActivities.OrderBy(a => a.Id).Take(20); 

//Now you can query theActivities 

참고 그러나 절을 MyDomains의 각 항목에 대해 추가됩니다 WHERE 한 이후, 다소 긴 SQL 쿼리로 끝날 것이다.

업데이트 : 실제로는 작동하지 않습니다. 쿼리식이 실제로 쿼리 될 때 평가되므로 모든 Except 절이 domain 변수 (마지막 값 집합)에 대해 동일한 값을 사용합니다.

내가 생각할 수있는 유일한 해결책은 데이터를 가져 오기 위해 dinamically SQL 명령을 생성하는 것입니다. 나는이 조인을 추가로 수행해야한다는 생각,

var whereClauses=new List<string>(); 

for(int i=0; i<MyDomains.Length; i++) { 
    whereClauses.Add(string.Format("(Referrer like {{{0}}})", i)); 
} 

var sqlFormattedDomains=MyDomains.Select(d => string.Format("%{0}%", d)).ToArray(); 

var sqlCommand=string.Format(
    "select top 20 * from Activities where (not Referrer is null) and (not ({0})) order by Id", 
    sqlFormattedDomains.Join(" or ")); 

var x=dc.ExecuteQuery<Activities>(sqlCommand, sqlFormattedDomains); 

당신은 SearchResults.Count() == 0 상태의 SQL 명령을 확장해야합니다 : 지금은 코드를 검증 할 방법이 없지만, 이런 약 일 것 절을 다른 테이블에 추가하십시오.

+0

아니요, foreach의 각 반복은 그것을 보충하는 대신 이전의 것보다 우선합니다. 따라서 목록에있는 마지막 항목으로 계산됩니다. +1 좋은 생각을위한 tho. – tsilb

+0

내가 제안한 대체 솔루션이 맞습니까? – Konamiman

0

내가 올바르게, 당신은 누구의 추천자 필드 중 하나를 포함하지 않는 ID에 의해 정렬 된 상위 20 활동을 가져올

&& !MyDomains.Contains(a.Referrer) 

를 추가하는 트릭

+0

아니요, 추천자는 완전한 형식의 URL이고 MyDomains는 루트 도메인입니다. {a.com, b.com}에는 {http://www.a.com/folder/file.htm?c=d&e=f}가 포함되어 있지 않습니다. – tsilb

+0

그러면 물건이 좀 더 재미있게 만들어집니다. – Murph