У меня возникли проблемы с поиском лучшего способа сделать это, и я буду признателен за любую помощь.
По сути, я настраиваю фильтр, который позволяет пользователю просматривать историю элементов аудита, связанных с произвольным «фильтром» имен пользователей.
Источником данных является база данных SQL Server, поэтому я беру «источник» IQueryable. (либо прямая ссылка на таблицу из объекта контекста db, либо, возможно, IQueryable, полученный в результате дополнительных запросов), применяя фильтр WHERE, а затем возвращая результирующий объект IQueryable .... но я немного не понимаю, как это сделать выполнить ИЛИ с использованием этого подхода.
Я подумал о том, чтобы пойти по пути выражений, потому что я знаю, как их ИЛИ, но я не смог понять, как это сделать с помощью оценки типа «Содержит», поэтому в настоящее время я использую UNION, но я боюсь, что это может негативно повлиять на производительность, и мне интересно, может ли это дать мне именно то, что мне нужно, если другие фильтры (в дополнение к фильтрации имени пользователя, показанной здесь) добавляются в произвольном порядке.
Вот мой пример кода:
public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source)
{
// Take allowed values...
List<string> searchStrings = new List<string>();
// <SNIP> (This just populates my list of search strings)
IQueryable<X> oReturn = null;
// Step through each iteration, and perform a 'LIKE %value%' query
string[] searchArray = searchStrings.ToArray();
for (int i = 0; i < searchArray.Length; i++)
{
string value = searchArray[i];
if (i == 0)
// For first step, perform direct WHERE
oReturn = source.Where(x => x.Username.Contains(value));
else
// For additional steps, perform UNION on WHERE
oReturn = oReturn.Union(source.Where(x => x.Username.Contains(value)));
}
return oReturn ?? source;
}
Кажется, это неправильный способ делать что-то, но, похоже, он работает, Итак, мой вопрос первый, есть ли лучший способ сделать это? Кроме того, есть ли способ сделать «Содержит» или «Нравится» с выражениями?
(Отредактировано, чтобы исправить мой код: при откате к рабочему состоянию для публикации я, по-видимому, не откатился достаточно далеко достаточно :))
=========================================== ==
ETA: Согласно данному решению, вот мой новый код (на случай, если кто-то, читающий это, заинтересован):
public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source)
{
List<string> searchStrings = new List<string>(AllowedValues);
// <SNIP> build collection of search values
string[] searchArray = searchStrings.ToArray();
Expression<Func<X, bool>> expression = PredicateBuilder.False<X>();
for (int i = 0; i < searchArray.Length; i++)
{
string value = searchArray[i];
expression = expression.Or(x => x.Username.Contains(value));
}
return source.Where(expression);
}
(Одно предостережение, которое я заметил: в соответствии с примером PredicateBuilder пустая коллекция поисковых строк вернет false (false || value1 || ...), тогда как в моей исходной версии я предполагал, что пустой список должен просто переходить в нефильтрованный источник. По мере того, как я думал об этом больше, новая версия, кажется, имеет больше смысла для моих нужд , поэтому я принял это)
========================================== ===