Как выполнить оператор IN в стиле SQL в LINQ to Entities (Entity Framework), если Contains не поддерживается?

Я использую LINQ to Entities (не LINQ to SQL), и мне не удается создать запрос в стиле IN. Вот мой запрос на данный момент:

var items = db.InventoryItem
                .Include("Kind")
                .Include("PropertyValues")
                .Include("PropertyValues.KindProperty")
                .Where(itm => valueIds.Contains(itm.ID)).ToList<InventoryItem>();

Однако когда я это делаю, возникает следующее исключение:

LINQ to Entities does not recognize the method 'Boolean Contains(Int64)' method, and this method cannot be translated into a store expression.

Есть ли у кого-нибудь обходной путь или другое решение для этого?

Какой тип valueIds?

Drew Noakes 13.12.2010 21:11
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
13
1
14 525
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Вам нужно либо использовать это:

.Where(string.Format("it.ID in {0}", string.Join(",", valueIds.ToArray())));

или создайте часть WHERE динамически, как в сообщении это.

P.S. - Информация была обновлена, и этот ответ обновлен следующим образом для сохранения актуальности:

Указанная ссылка содержит следующее обновление:

...in EF4 we added support for theContains method and at least in thisspecific case for collection-valuedparameters. Therefore this kind ofcode now works right out of the boxand it is not necesary to use anyadditinal expression building method:

var statusesToFind = new List<int> {1, 2, 3, 4};
var foos = from foo in myEntities.Foos
           where statusesToFind.Contains(foo.Status)
           select foo;

Я заметил, что даже при передаче where в виде строки IN преобразуется во многие операторы OR ..

Boris Callens 28.04.2010 11:40

@ liggett78 Сейчас я столкнулся с этой ситуацией из-за того, что пользовательский ORM не поддерживает .Contains или .Any. Я пытаюсь реализовать первое решение, но не знаю, как оно работает - как предложение .Where принимает нефункциональный аргумент?

jedd.ahyoung 13.02.2014 09:47

Мой обходной путь - преобразовать результат сущностей в список и после, которые применяют Contains ().

Пример:

var items = db.InventoryItem
                .Include("Kind")
                .Include("PropertyValues")
                .Include("PropertyValues.KindProperty")
                .ToList()
                .Where(itm => valueIds.Contains(itm.ID));

Это ужасно, иногда я действительно ненавижу обручи, которые заставляет EF прыгать, чтобы что-то делать. Но это работает, просто плохо смотрится в коде. Спасибо

Ryan O'Neill 24.02.2010 17:26

Фактически, этот «обходной путь» берет все данные из базы данных и фильтрует их на C#. Если у вас много данных, это существенно снизит производительность.

ovolko 15.04.2010 14:43

-1: вы не хотите гидратировать коллекцию перед применением дополнительного фильтра.

IAbstract 10.05.2011 21:05

В некоторых случаях для этого можно использовать метод расширения Linq Any:

var userIds = new[] { 1, 2, 3 };

from u in Users
     where userIds.Any(i => i==u.Id)
     select u;

Сгенерированный SQL в таком случае выглядит довольно странно, но, как и многие другие SQL-запросы, сгенерированные Linq-to-Entities, он может быть слишком многословным для человека, но на практике выполняется быстро.

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[DisplayName] AS [DisplayName], 
FROM [dbo].[Users] AS [Extent1]
WHERE  EXISTS (SELECT 
    1 AS [C1]
    FROM  (SELECT 
        [UnionAll1].[C1] AS [C1]
        FROM  (SELECT 
            1 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]
        UNION ALL
            SELECT 
            2 AS [C1]
            FROM  ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
    UNION ALL
        SELECT 
        3 AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
    WHERE [UnionAll2].[C1] = [Extent1].[Id]
)

Как упоминал Диего Б. Вега в эта почта (второй ответ), Contains теперь должен работать в EF4.

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