2016-11-07 4 views
1

Я здесь, чтобы задать вопрос о том, как выглядит код, когда дело доходит до расширенной фильтрации в C# с LINQ. У меня есть опыт работы с Linq, но это то, что было вне моего понимания.Расширенная фильтрация в linq

Допустим, у нас есть класс Item, который имеет свойства (string)Name, (bool)New и (int)Price и пользователи должны ввести свои фильтры и получить результаты, которые им нужны.

Допустим, мы помещаем 5 объектов в список list, который представляет собой список предметов.

new Item("Pen",true,12); 
new Item("PostIt",false,35); 
new Item("Phone",true,140); 
new Item("Watch",true,5); 
new Item("Lavalamp",false,2); 

Теперь я woud хотел обработать эту информацию, чтобы получить .. Все новые времена, которые стоят более 10. Я знаю, что могу сделать это с

List<Item> Results = list.where(item => item.Price> 10 && item.New).ToList(); 

но что, если пользователь хочет получить все которые стоят более 10 независимо от того, являются ли они новыми или нет. Я не могу изменить запрос во время выполнения, чтобы он соответствовал потребностям, и я не думаю, что создание запроса для каждой возможной комбинации входных параметров - правильный способ сделать это ... Может ли кто-нибудь дать мне пример о том, как это сделать?

+0

Возможно это? [Источник CS-Script] (https://csscriptsource.codeplex.com/wikipage?title=Choosing%20Compiler%20Engine) – Fabio

+0

LINQ является составным. Вы можете условно применять другие фильтры, но вы хотите по одному - не нужно указывать их все в одном 'Where'. – Luaan

+0

Возможный дубликат [Объединить запросы LinQ] (http://stackoverflow.com/questions/9804683/combine-linq-queries), это был запрос, который я использовал для объединения запросов, но вы можете создать большой список вещей в зависимости от различные критерии, а затем запустить их. – BugFinder

ответ

5

Вы можете определить базовый запрос

var result = list.Where(item=> item.Price > 10); //DON'T Call ToList() here 

if(someCondition) 
    result = result.Where(item=> item.New); 

//in the end you are calling 

return result.ToList(); 

Like @MikeEason сказал, что вы не хотите звонить ToList() на первый результат, потому что это будет выполнить запрос. Ваша цель - построить сложный запрос и выполнить его только один раз. Из-за этого это делается, когда вы возвращаете результат.

+2

Стоит отметить, что этот метод эффективно * создает * запрос и выполняется только тогда, когда он попадает в '.ToList()'. –

+0

@MikeEason Да, я собирался написать это. – mybirthname

+0

ToList() не был действительно важной частью вопроса, но спасибо, что заметил его и написал ответ вокруг него. Причина, по которой я прошу об этом, - это проект, который может потребовать до 50,60 дополнительных фильтров. Спасибо за ответ, он ответил на мой вопрос! – DethoRhyne

3

Если у вас есть только эти три условия, то вы можете создать свой запрос в несколько этапов:

IEnumerable<Item> result=list; 
int Price=10; 
bool FilterByPrice, bool FilterByNew;//Set this variables in your environment 
if(FilterByPrice) 
    result=result.Where(item => item.Price> Price); 
if(FilterByNew) 
    result=result.Where(item => item.New); 

Ваш запрос будет выполняться при вызове ToList метода или пошли вы перебирать результат запроса благодаря deferred execution.

+0

Сначала я думал, что будет более простой метод, но если это так, черт возьми, там будет много. Спасибо! Я отвечу на ваш ответ, но я выберу ответ mybirthname как «Ответ», поскольку он имеет больше оборотов, а код выглядит немного чище. – DethoRhyne

1

Так что скажем, что ваши предметы существуют в вашей базе данных, и вы хотите их запросить. У пользователя есть флажок, если он хочет видеть только новые элементы или все из них. Если флажок установлен, вы устанавливаете для него значение bool.

//Compose the query 
var results = _db.Where(item => item.Price > 10); 
//still composing 
if(onlyNewItems) 
{ 
    results = results.Where(item => item.New); 
} 
//ToList() executes the query, data is returned; 
return results.ToList(); 

Это не вызывает запрос дважды. Фактически, пока вы не материализуете свой запрос, вы все еще его составляете. Если вы вернете его сейчас, он будет иметь тип IQueryable<T>. Только после того, как вы позвоните .ToList(), ваш запрос действительно выполнен, и вы получите IEnumberable<T> в этом случае List<T> назад.

+0

Большое спасибо за объяснение, я этого не знал. Я думал, что все запросы linq рассматриваются как запрос. – DethoRhyne

0
List<Item> Results = list.where(item => item.Price > 10 
             && (condition ? item.New : true)).ToList(); 

вы можете продлить этот путь. просто перейдите true, если ваше состояние ложно, и это похоже на то, что ничего не произошло.

Смежные вопросы