Как вы выполняете оператор "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>();
</inventoryitem>

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

LINQ to Entities не распознает метод "Boolean Contains (Int64)", и этот метод не может быть переведен в выражение хранилища.

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

5 ответов

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

.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 **********.Foos
 where statusesToFind.Contains(foo.Status)
 select foo;
</int>


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

var userIds = new[] { 1, 2, 3 };
from u in Users
 where userIds.Any(i => i==u.Id)
 select u;

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

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]
)


Как упоминалось Diego B Vega в этот пост (второй ответ), Contains теперь должен работать в EF4.


Кто-то создал выражение для этого сценария... Я нашел его и захватил, но не могу вспомнить, где я нашел исходный источник. Я отправлю код немного. На данный момент это маркер для меня, чтобы вернуться.


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

Пример:

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

licensed under cc by-sa 3.0 with attribution.