Предложение Linq Where с динамическими условиями

Для вызова API у меня есть строка, отправляемая для получения соответствующих предметов инвентаря. Следующее работает по назначению:

    public IEnumerable<Inventory> GetInventoryByItem(string item)
    {
        return _ctx.Pairs
            .Include(x => x.Attribute)
            .Where(x => (x.Attribute.Item == item));
    }

Моя проблема заключается в том, чтобы добавить несколько условий к функции, чтобы получить что-то в результате:

    public IEnumerable<Inventory> GetInventoryByItem(string[] items)
    {
        return _ctx.Pairs
            .Include(x => x.Attribute)
            .Where(x => foreach(string item in items){ return x.Attribute.Item == item });
    }

Вышеуказанная функция явно не работает. Я знаю, что могу получить коллекцию элементов, вызвав вышеуказанную функцию извне в цикле, но меня беспокоит то, что я попадаю в базу данных с несколькими почти идентичными операторами, когда я мог бы просто объединить их в один. Есть ли эффективный способ сделать это?

Используйте items.Containsвнутри предложение Where.

mjwills 20.02.2019 00:22
.Where(x => items.Contains(x.Attribute.Item)); или .Where(x => items.Any(item => x.Attribute.Item == item));
Rufus L 20.02.2019 00:53

@NetMage, о, верно! спасибо, удалил

Rufus L 20.02.2019 00:53
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
87
3

Ответы 3

Итак, вам нужна универсальная функция, которая принимает на вход последовательность объектов некоторого класса и последовательность предикатов свойств этого класса, и вы хотите на выходе последовательность, содержащую эти объекты из входной последовательности, где все предикаты возвращали бы true

Например:

IEnumerable<Person> persons = ...
var predicates = [0] person is born in 1961
                 [1] person is born in Honolulu
                 [2] person is a politician

В качестве вывода вам нужна последовательность со всеми политиками, родившимися в Гонолулу в 1961 году.

Давайте сделаем это как метод расширения, чтобы вы могли использовать его как инструкцию LINQ. См. демистифицированные методы расширения

Что вы делаете, так это объединяете утверждения Where. Параметр predicate, где Func<TSource, bool>. Итак, нам нужна последовательность Func<TSource, bool> в качестве предикатов.

static IEnumerable<TSource> Where( this IEnumerable<TSource> source,
    IEnumerable<Func<TSource, bool>> predicates)
{
    // TODO: handle null source and null predicates

    IEnumerable<TSource> result = source;
    foreach (Func<TSource, bool> predicate in predicates)
    {
        result = result.Where(predicate);
    }
    return result;
}

Пример использования:

IEnumerable<Person> persons = ...
var honoluluPresidents = persons.Where(new[]
{
     person => person.BirthPlace == "Honolulu",
     person => person.BirthDate.Year == 1961,
     person => person.Job == "politician",
});

Просто comme bonjour!

Но чем это лучше, чем сочетание предикатов с и/или? Я также думаю, что вы что-то упустили (например, []) в своем примере использования.

Seva 20.02.2019 12:52

Что ж, это был ваш выбор не предоставлять вариант использования, когда программное обеспечение выдает неизвестную последовательность предикатов. Возможно, оператор создал список предикатов, выбрав предикаты из поля выбора. Ваше предложение использовать последовательность строк еще хуже, потому что нет абсолютно никакой проверки того, что используемые строки представляют правильные предикаты. Вы правы насчет [] . Не стесняйтесь улучшить ответ

Harald Coppoolse 20.02.2019 13:01

Я не говорил о строках — я говорил о логических операторах «&&» и «||».

Seva 20.02.2019 13:38

Тем не менее, в своем вопросе вы пишете GetInventoryByItem(string[] items), я предположил, что вы хотите идентифицировать предикаты в вашем where, используя последовательность строк. Если это не так, то что вы имели в виду?

Harald Coppoolse 20.02.2019 14:39

Но это не мой вопрос :D, ОП - это @анестетик. Я думаю, что он хотел сделать, это отфильтровать набор чего-то x на основе того, имеет ли этот x все атрибуты элемента, переданные в качестве параметра.

Seva 20.02.2019 14:48

Ну, вы можете использовать Any

public IEnumerable<Inventory> GetInventoryByItem(string[] items)
{
        return _ctx.Pairs
            .Include(x => x.Attribute)
            .Where(x => items.Any(a=> a == x.Attribute.Item));
  // OR
     return _ctx.Pairs
            .Include(x => x.Attribute)
            .Where(x => items.Contains(x.Attribute.Item));
}

Может быть, вы имели в виду .All() под своим foreach?

public IEnumerable<Inventory> GetInventoryByItems(string[] items)
{
    return _ctx.Pairs
        .Include(x => x.Attribute)
        .Where(x => items.All(item => x.Attribute.Item == item));
}

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