Создание IQueryable для равных int32?
Я пытаюсь создать расширение запроса, которое сравнивало бы значение столбца int sql с нулевым значением и значением. Но я уже более 8 часов пытаюсь найти какое-либо рабочее решение.
Я уже нашел много помощи на этой стороне. Но все замечания мне не помогли.
Я так много раз менял код, но ничего не получалось. Я хочу создать нечто похожее на WHERE ManagerID IN (10,20,30)
Основной код
IQueryable<Users> query = _context.CreateObjectSet<Users>();
query = query.IsMember(a => a.ManagerID, new Int32?[] { 10,20,30 });
return query.ToList();
В настоящее время во время выполнения запроса.ToList(); это возвращает мне
Невозможно создать постоянное значение типа 'System.Object'. В этом контексте поддерживаются только примитивные типы или типы перечисления.
public static IQueryable<T> IsMember<T>(this IQueryable<T> source, Expression<Func<T, Int32?>> stringProperty, params Int32?[] searchTerms)
{
if (searchTerms == null || !searchTerms.Any())
{
return source;
}
Expression orExpression = null;
foreach (var searchTerm in searchTerms)
{
var searchTermExpression = Expression.Constant(searchTerm, typeof(object)); // <<--- This cast would make it no longer a primitive type
var containsExpression = Expression.Call(stringProperty.Body, typeof(Int32?).GetMethod("Equals"), searchTermExpression);
orExpression = BuildOrExpression(orExpression, containsExpression);
}
var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, stringProperty.Parameters);
return source.Where(completeExpression);
}
private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
{
return existingExpression == null ? expressionToAdd : Expression.OrElse(existingExpression, expressionToAdd);
}
Строка, помеченная для предоставления константе другого типа данных, действительно является причиной проблемы, но если я не сделаю ее объект типа, выражение не будет работать, так как оно не может соответствовать Int32? тип данных.
Кто-нибудь может мне помочь?
Спасибо
=============================================
Дополнительная информация
Это действительно иметь большую картину. Я просто хочу создать что-то более динамичное, что можно было бы использовать и в других проектах.
Я хотел бы использовать некоторые функции, которые будут выглядеть привлекательнее, чем все эти мультилинии
query = query.Like(a => a.UserName, filter.UserName, true);
query = query.Equals(a => a.UserTown, filter.UserTown, true);
query = query.IsMember(a => a.Division, filter.Division); // is an array of possible divisions
это работало нормально для Like и Equals, которые основаны на строках. Но хочу иметь аналогичный продукт для (обнуляемых) целых чисел
Я был вдохновлен следующим постом. Который создал функцию поиска (которую я переименовал для моего проекта в "Мне нравится")
Я хотел создать другие похожие. последнее логическое значение должно проверять, разрешено ли значение NULL в столбце или нет.
Причина также использовать расширение, состоит в том, что у меня также есть много фильтров на моей странице фильтра. С этим расширением я бы легко проверил в начале функции "Мне нравится" и "Равно", был ли задан фильтр, не проверяя, имеет ли мой фильтр значение 20x.
public static IQueryable<T> Like<T>(this IQueryable<T> source, Expression<Func<T, string>> stringProperty, string searchTerm, bool isnullValueAllowed)
if (String.IsNullOrEmpty(searchTerm))
{
return query;
}
2 ответа
Непонятно, почему вы хотите создать это расширение, так как вы можете просто написать что-то вроде:
query.Where(user => (new[]{10,20,30}).Contains(user.ManagerId)).ToList();
Однако, предполагая, что реальный вариант использования несколько сложнее, чем приведенный вами пример, вы не могли бы построить свое выражение как сравнение с константой Int32 или сравнение с нулем, в зависимости от того, searchTerm.HasValue()
было правдой?
Вам нужно использовать оператор равенства ==
а не Equals
метод здесь. Это на самом деле делает ваш код выражения немного проще:
foreach (var searchTerm in searchTerms)
{
var comparison = Expression.Equals(stringProperty.Body,
Expression.Constant(searchTerm));
orExpression = BuildOrExpression(orExpression, comparison);
}
Конечно, как уже упоминалось, вам не нужно создавать выражение, представляющее ИЛИ каждого из этих сравнений, вы можете просто использовать Conatains
на множестве в лямбде, и поставщик запросов сделает все это для вас.