Итак, принципиально, что вы хотите сделать здесь, есть предложение IN
, в котором вы указываете кучу значений для поля, и вы хотите, чтобы строки, значения которых для этого столбца находились в этом наборе.
У CAML действительно есть предложение IN, которое вы можете использовать, но, к сожалению, LINQ to Sharepoint не предоставляет никаких средств для создания предложения IN; поставщик просто не поддерживается.
Вы пытаетесь использовать немного взлома, чтобы обойти эту проблему, пытаясь выполнить сравнение строк, а не использовать правильные операторы, и вы сталкиваетесь с ловушками, которые строят все ваши операции. Это просто плохо подходит для этой задачи.
Поскольку, как я уже сказал, вы не можете заставить LINQ to SharePoint использовать IN, один вариант просто заключался бы в том, чтобы не использовать LINQ, создавать CAML вручную и выполнять его с использованием стандартной объектной модели сервера. Но это не весело.
Что мы может действительно есть серия проверок ИЛИ. Мы увидим, является ли это значение столбца первым значением, или вторым, или третьим и т. Д. Для всех значений в вашем наборе. Это фактически идентично предложению IN, это намного больше подробностей.
Теперь это приводит нас к проблеме того, как OR вместе неизвестное количество сравнений. Если бы это было ANDs, это было бы легко, мы бы просто вызвали Where
внутри цикла, и это было бы и те предложения N.
Вместо этого нам понадобятся выражения. Мы можем вручную построить дерево выражений самим из динамического числа предложений OR, а затем поставщик запросов сможет разбирать его просто отлично.
Наш новый метод, WhereIn
, который будет фильтровать запрос ко всем элементам, где данное значение свойства находится в наборе значений, необходимо будет принять запрос, селектор свойств того, какое свойство мы используем, и набор значений того же типа для сравнения с ним. После того, как у нас есть, просто создать выражение сравнения доступа к свойствам вместе с каждым значением ключа, а затем ORing всех этих выражений.
public static IQueryable<TSource> WhereIn<TSource, TKey>(
this IQueryable<TSource> query,
Expression<Func<TSource, TKey>> propertySelector,
IEnumerable<TKey> values)
{
var t = Expression.Parameter(typeof(TSource));
Expression body = Expression.Constant(false);
var propertyName = ((MemberExpression)propertySelector.Body).Member.Name;
foreach (var value in values)
{
body = Expression.OrElse(body,
Expression.Equal(Expression.Property(t, propertyName),
Expression.Constant(value)));
}
return query.Where(Expression.Lambda<Func<TSource, bool>>(body, t));
}
Теперь назвать это нам просто нужно запрос, свойство мы фильтрацию и сбор значений:
var q2 = vendorSearchesQuery.WhereIn(vendor => vendor.SearchTypeId
, strCheckedCategories.Split(';'));
и вуаля.
Хотя я бы ожидать, что работать как есть, вы может нужно вызвать WhereIn
перед темSelect
. Он может работать не совсем корректно с уже нанесенным на карту SearchTypeId
.
if 'strCheckedCategories = 2', как бы' 2' содержать '12',' 20' и '21'? –
@KingKing это я думаю, наоборот, 12 20 21 содержит 2 –
Отредактированный вопрос, чтобы выправить это, спасибо. – LFurness