Создание 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 на множестве в лямбде, и поставщик запросов сделает все это для вас.

Другие вопросы по тегам