У меня возникли проблемы с поиском лучшего способа сделать это, и я был бы признателен за любую помощь.
По сути, я настраиваю фильтр, который позволяет пользователю просматривать историю элементов аудита, связанных с произвольным «фильтром» имен пользователей.
Источник данных - это база данных 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 || ...), тогда как в моей исходной версии я предполагал, что пустой список должен просто соединиться снефильтрованный источник. Как я уже думал об этом, новая версия, кажется, имеет больше смысла для моих потребностей, поэтому я принял это)
=============================================