Я пытаюсь добавить пользователя в команду, выполнив поиск по списку пользователей.
Я использую linq для поиска данных, чтобы найти совпадение на основе ряда полей.
data = data.Where(x =>
x.Name.ToLower().Contains(filter) ||
x.Surname.ToLower().Contains(filter) ||
x.PhoneNumber.ToLower().Contains(filter) ||
x.Email.ToLower().Contains(filter) ||
x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))
);
Однако результаты работают только с именем, фамилией и электронной почтой.
При поиске по всем полям выдаются, казалось бы, случайные пользователи, а не те, которые соответствуют указанному фильтру.
Вы уверены, что вам нужно All, а не Any. Обратите внимание, что All для пустой коллекции всегда верно в LINQ-to-Objects.
Данные будут списком пользователей с именем. Адрес электронной почты, номер телефона и т. д. Фильтром будет то, что вы вводите в строку поиска. Например, человек или ввод «Джо» должны вызывать «Джон», но вместо этого вызывают такие вещи, как «Эми».
@MylesLouw Это недостаточно конкретные примеры данных. Поскольку у вас есть много условий ИЛИ, существует так много потенциальных совпадений, которые можно сделать. Кроме того, в одних местах вы используете .ToLower(), а в других нет. Это предназначено? filter был .ToLower()ed?
Однако результаты работают только с именем, фамилией и электронной почтой.
Я думаю, что PhoneNumber тоже должно быть хорошо.
При поиске по всем полям выдаются, казалось бы, случайные пользователи, а не те, которые соответствуют указанному фильтру.
Enumerable.All для пустой коллекции всегда будет true:
Console.WriteLine(new int[]{}.All(i => false)); // prints True
Попробуйте использовать что-то вроде:
data = data.Where(x =>
... || (x.AthleteTeams.Any() && (
x.AthleteTeams.All(x => x.Team.Name.Contains(filter)) ||
x.AthleteTeams.All(x => x.Athlete.AthleteGender.Equals(filter)) ||
x.AthleteTeams.All(x => x.Athlete.AthleteRace.Equals(filter))))
);
Также, возможно, вам действительно нужно Any вместо All в первую очередь:
data = data.Where(x =>
...
|| x.AthleteTeams.Any(x => x.Team.Name.Contains(filter)
|| x.Athlete.AthleteGender.Equals(filter)
|| x.Athlete.AthleteRace.Equals(filter))
);
Я предполагаю, что вы не хотите, например, найти всех пользователей, которые AthleteTeams имеют ВСЕ одинаковое имя команды. Это будет означать, что у вас есть несколько команд с похожим названием.
Я предполагаю, что вы на самом деле хотите найти всех пользователей, которые AthleteTeams содержат хотя бы ОДНУ команду с совпадающим именем, например. Поэтому используйте Any, а также используйте только один запрос AthleteTeams вместо трех:
....
x.AthleteTeams.Any(x => x.Team.Name.Contains(filter)
|| x.Athlete.AthleteGender.Equals(filter)
|| x.Athlete.AthleteRace.Equals(filter))
Однако я нахожу эту логику фильтра странной и подверженной ошибкам. У вас будет медленная производительность поиска и много ложных совпадений, потому что всегда что-то совпадает, а пользователь не знает, почему. Лучше предоставьте поиск по наиболее распространенным свойствам, таким как имена и номер телефона, не начинайте поиск, пока пользователь не введет как минимум 3 символа, и предоставьте конкретный поиск по команде.
Он возвращает, казалось бы, случайных пользователей вместо тех, которые соответствуют указанному фильтру --> Можете ли вы привести конкретный пример сценария и указать значения для data, filter, ожидаемого результата и фактического результата?