2015-01-14 1 views
0

Linq-To-CRM에서 쿼리 결과를 동적으로 필터링하려고합니다.Linq to CRM IQueryable Issue

기본적으로 표준 쿼리가 있으며 특정 기준에 따라 특정 필터를 추가 할 수 있기를 원합니다. 그러나이 오류가 발생합니다 ... 'Where'메서드는 'Select'메서드를 수행 할 수 없거나 지원되지 않습니다. 지원되지 않는 메소드를 호출하기 전에 지원되는 메소드로 조회를 작성하거나 'AsEnumerable'또는 'ToList'메소드를 호출하십시오.

간단한 코드 샘플을 아래에 표시합니다. 누구든지 linq-to-sql을 사용하여이 작업을 수행 할 수 있는지 알고 있습니까? 동적으로 추가해야 할 수도 있고 없을 수도있는 5 개 또는 6 개의 개별 필터가있을 수 있습니다. 물론 필터의 모든 가능한 조합에 대해 별도의 쿼리를 정의 할 수 있지만 이것은 과도한 것처럼 보입니다 & 가능하면이 문제를 피하고 싶습니다.

IQueryable<CourseProduct> coursesVar = 
(
    from a in context.CreateQuery("vs_course") 
    join b in context.CreateQuery("product") on a["vs_product"] equals b["productid"] 
    join c in context.CreateQuery("productpricelevel") on b["productid"] equals c["productid"] 
    join d in context.CreateQuery("vs_coursetype") on a["vs_coursetype"] equals d["vs_coursetypeid"] 
    join e in context.CreateQuery("vs_coursearea") on a["vs_coursearea"] equals e["vs_courseareaid"] 
    where a["vs_product"] != null // ensure product is set 
    && a["vs_coursetype"] != null 
    && a["vs_coursearea"] != null 
    && a["vs_price"] != null 
    where b["price"] != null 
    where c["pricelevelid"] != null 
    && (Guid)c["pricelevelid"] == pricelistId // ensure price list is set (and matches the correct pricelist) 
    && c["amount"] != null 
    select new CourseProduct 
    { 
     CourseId = (Guid)a["vs_courseid"], 
     CourseCode = !a.Contains("vs_code") ? string.Empty : (string)a["vs_code"], 
     CourseName = !a.Contains("vs_name") ? string.Empty : (string)a["vs_name"], 
     CourseType = !a.Contains("vs_coursetype") ? string.Empty : ((EntityReference)a["vs_coursetype"]).Name, 
     CoursePrice = !a.Contains("vs_price") ? -997 : ((Money)a["vs_price"]).Value, 
     ProductPrice = !b.Contains("price") ? -996 : ((Money)b["price"]).Value, 
     PricelistItemPrice = !c.Contains("amount") ? -995 : ((Money)c["amount"]).Value, 
     CurrencySymbol = currencySymbol, 
     ActualType = !d.Contains("vs_type") ? -999 : ((OptionSetValue)d["vs_type"]).Value, 
     CourseTypeId = (Guid)d["vs_coursetypeid"], 
     CourseAreaId = (Guid)e["vs_courseareaid"], 
     CourseTypeCode = !d.Contains("vs_code") ? string.Empty : (string)d["vs_code"], 
     CourseAreaCode = !e.Contains("vs_code") ? string.Empty : (string)e["vs_code"] 
    } 
); 

// now try and add some filters dynamically 
coursesVar = coursesVar.Where(i => i.CourseCode == "X"); 
coursesVar = coursesVar.Where(i => i.CourseAreaCode == "Y"); 

var finalList = coursesVar.ToList(); // this line throws the error 
+0

IQueryable로 설정하지 않고 목록으로 설정하고 쿼리 끝에 ToList() 캐스트 – Sxntk

+0

하지만 단 하나의 쿼리로 실행되지는 않습니까? 이렇게하면 전체 결과 집합이 반환되고 결과적으로 전체 집합에서 필터링됩니다. 이는 처음부터 IQueryable을 사용하여 피하려고하는 것입니다. – user2425239

+0

나는 쿼리가 "from ... where ... new ... select ... where ... toList()"와 같아 보인다. Linq-Crm은 매우 엄격하며 "from - where - select"구조 만 따라갈 수 있습니다. 왜 첫 번째 쿼리에서 마지막 2 개를 추가하지 않습니까? – Sxntk

답변

0

지원되지 않습니다. 그렇지 않으면 linq-2-sql은 똑똑해야만 select new {}에있는 전체 코드를 추가 필터로 변환하고 다시 SQL로 변환하여 데이터베이스에서 수행 할 수 있습니다. 즉

그래서 당신은 추가해야합니다 ... 킬러 기능이 될 것입니다 귀하의 경우

뭔가

from a in context.CreateQuery("vs_course") 
<and the rest of your complex join> 

그리고

// now try and add some filters dynamically 
coursesVar = coursesVar.Where(|rephrase in terms of the Original query|} 
먼저 필터를 할 다시

같은} {선택의 새로운 전

마지막으로

Select new 

이것은 분명히 동적 필터의 '깨끗한'코드가 원래 쿼리 스타일에서 더 많이 표현되어야한다는 단점이 있습니다.

필터를 추가하기 전에 구체화해야합니다. 이는 필터 전/후에 리턴 된 행 시작 수 사이의 비율에 달려 있습니다.