Как выполнить оператор IN в стиле SQL в LINQ to Entities (Entity Framework), если Contains не поддерживается? - PullRequest
13 голосов
/ 30 ноября 2008

Я использую 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 не распознает метод метода Boolean Contains (Int64), и этот метод нельзя преобразовать в выражение хранилища.

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

Ответы [ 4 ]

8 голосов
/ 13 декабря 2010

В некоторых случаях для этого можно использовать метод расширения 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]
)
7 голосов
/ 30 ноября 2008

Вы должны использовать это:

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

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

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

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

... в EF4 мы добавили поддержку Содержит метод и, по крайней мере, в этом особый случай для коллекционной стоимости параметры. Поэтому этот вид код теперь работает прямо из коробки и использовать необязательно метод построения дополнительного выражения:

var statusesToFind = new List<int> {1, 2, 3, 4};
var foos = from foo in myEntities.Foos
           where statusesToFind.Contains(foo.Status)
           select foo;
1 голос
/ 15 декабря 2010

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

0 голосов
/ 03 февраля 2010

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

Пример:

var items = db.InventoryItem
                .Include("Kind")
                .Include("PropertyValues")
                .Include("PropertyValues.KindProperty")
                .ToList()
                .Where(itm => valueIds.Contains(itm.ID));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...