#c# #linq
Вопрос:
Я пытаюсь выполнить запрос с помощью EF. Пользователь может использовать до 3 поисковых слов, но они не требуются. Как написать запрос EF, который будет работать как И для всех используемых поисковых слов, но сможет удалить И для любого пустого поискового слова?
Например, я хочу, чтобы следующие два элемента возвращали первые два элемента в массиве для s1=» мобильный», s2= » и s3=»ноутбук». Он ничего не возвращает. Он должен вернуть первые два, если s2 изменен на s2= «берк».
Пример:
using System;
using System.Linq;
public class Simple {
public static void Main() {
string[] names = { "Burke laptop mobile", "laptop burke mobile", "Computer Laptop",
"Mobile", "Ahemed", "Sania",
"Kungada", "David","United","Sinshia" };
//search words
string s1 = "mobile";
string s2 = "";
string s3 = "laptop";
var query = from s in names
where (!string.IsNullOrEmpty(s1) amp;amp; s.ToLower().Contains(s1))
amp;amp; (!string.IsNullOrEmpty(s2) amp;amp; s.ToLower().Contains(s2))
amp;amp; (!string.IsNullOrEmpty(s3) amp;amp; s.ToLower().Contains(s3))
orderby s
select s.ToUpper();
foreach (string item in query)
Console.WriteLine(item);
}
}
Комментарии:
1. @Calculuswhiz Я использую базу данных в своем приложении, но изменил ее на массив, чтобы упростить вопрос
Ответ №1:
Вместо того, чтобы пытаться написать один where
оператор, вы можете при необходимости расширить существующий IQueryable<T>
(или IEnumerable<T>
, как в нашем примере кода) Where
, связав операторы в цепочку.
var query = names;
if (!string.IsNullOrEmpty(s1))
{
query = query.Where(x => x.Contains(s1));
}
if (!string.IsNullOrEmpty(s2))
{
query = query.Where(x => x.Contains(s2));
}
// ... (or make a foreach loop if s1,s2,s3 were an array.
var results = query.OrderBy(x => x).Select(x => x.ToUpper());
Where
Такая цепочка эквивалентна «соединению» всех предикатов вместе.
ИЗМЕНИТЬ:
Чтобы уточнить, почему ваша конкретная реализация не работает, это потому, что ваши amp;amp;
операторы неверны для данного варианта использования.
(string.IsNullOrEmpty(s1) || s.ToLower().Contains(s1)) amp;amp;
(string.IsNullOrEmpty(s2) || s.ToLower().Contains(s2)) amp;amp;
(string.IsNullOrEmpty(s3) || s.ToLower().Contains(s3))
Помните , что для этого amp;amp;
требуются как левые, так и правые операторы true
, поэтому в вашем случае !string.IsNullOrEmpty(s2) amp;amp; s.ToLower().Contains(s2)
это означает, что s2
всегда должно быть не-пусто/пусто.
Комментарии:
1. Я сделал что-то подобное, но это не возвращает результаты со всеми поисковыми запросами. Для этого нужны s1 И s2. Это вернет результаты, если s1.Содержит == истина и s2.Содержит == ложь. Я думаю, что я мог бы очистить результирующий набор, если ничего не будет возвращено ни для одного из содержащихся.
2. Нет, это будет работать так, как вам нужно, если оба
s1
иs2
НЕ пусты, это гарантирует, что он получит только результаты, содержащие обаs1
иs2
. Для приведенного вами примера вы должны использовать(IsNullOrEmpty(s1) || x.Contains(s1)) amp;amp; (IsNullOrEmpty(s2) || x.Contains(s2)) amp;amp; ...
3. @Heinrich Я привел пример, демонстрирующий, почему созданная мной реализация принципиально отличается от вашей, однако при редактировании я предоставил замену вашей логике, если вы захотите продолжить свой формат.
Ответ №2:
Пожалуйста, подумайте об этом:
using System;
using System.Linq;
public class Simple {
public static void Main() {
string[] names = { "Burke laptop mobile", "laptop burke mobile", "Computer Laptop",
"Mobile", "Ahemed", "Sania",
"Kungada", "David","United","Sinshia" };
//search words
string s1 = "mobile";
string s2 = "";
string s3 = "laptop";
var query = from s in names
where (s1 != null amp;amp; s.ToLower().Contains(s1))
amp;amp; (s2 != null amp;amp; s.ToLower().Contains(s2))
amp;amp; (s3 != null amp;amp; s.ToLower().Contains(s3))
orderby s
select s.ToUpper();
foreach (string item in query)
Console.WriteLine(item);
}
}
Ответ №3:
Если вы используете массив или список вместо нескольких строк, вы можете сделать что-то вроде
List<string> searchWords = new List<string>
{
"mobile",
"",
"laptop"
};
var query = names
.Where(n => searchWords
.Where(s => !string.IsNullOrEmpty(s))
.All(s => n.ToLower().Contains(s)))
.Select(n => n.ToUpper())
.OrderBy(n => n);
Это также более гибко, так как у вас может быть любое количество поисковых слов, без изменения запроса.