2015-01-14 4 views
0

Я пытаюсь динамически фильтровать результаты запроса в Linq-To-CRM.Linq To CRM IQueryable Issue

В принципе, у меня есть стандартный запрос и на основе определенных критериев я хочу, чтобы у вас есть возможность добавлять к нему определенные фильтры. Однако я получаю эту ошибку ... Метод «Где» не может следовать методу «Выбрать» или не поддерживается. Попробуйте написать запрос с помощью поддерживаемых методов или вызвать метод «AsEnumerable» или «ToList» перед вызовом неподдерживаемых методов.

Упрощенный образец моего кода показан ниже. Кто-нибудь знает, можно ли это сделать с помощью linq-to-sql? У меня потенциально есть 5 или 6 отдельных фильтров, которые я могу или не должен добавлять динамически. Я могу, конечно, определить отдельные запросы для всех возможных комбинаций фильтров, но это похоже на overkill. & Я хочу избежать этого, если это вообще возможно.

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, задан как List и в конце запроса, сделайте листинг ToList() – Sxntk

+0

Но тогда он не будет выполнен как один запрос точно? Это приведет к возврату всего возвращаемого набора результатов, и впоследствии я буду фильтровать весь набор, чего я пытаюсь избежать, используя IQueryable в первую очередь. – user2425239

+0

Я думаю, что запрос выглядит как «from ... where ... select new ... where ... 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 

Это, очевидно, имеет недостаток, заключающийся в том, что «чистый» код динамических фильтров должен быть больше сформулирован в стиле оригинального запроса.

Альтернатива заключается в материализации перед добавлением фильтров. Это будет зависеть от соотношения между количеством строк, которые будут возвращены до/после фильтра.