Я использую 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.
Есть ли у кого-нибудь обходной путь или другое решение для этого?





Вам нужно либо использовать это:
.Where(string.Format("it.ID in {0}", string.Join(",", valueIds.ToArray())));
или создайте часть WHERE динамически, как в сообщении это.
Указанная ссылка содержит следующее обновление:
...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 ..
@ liggett78 Сейчас я столкнулся с этой ситуацией из-за того, что пользовательский ORM не поддерживает .Contains или .Any. Я пытаюсь реализовать первое решение, но не знаю, как оно работает - как предложение .Where принимает нефункциональный аргумент?
Мой обходной путь - преобразовать результат сущностей в список и после, которые применяют Contains ().
Пример:
var items = db.InventoryItem
.Include("Kind")
.Include("PropertyValues")
.Include("PropertyValues.KindProperty")
.ToList()
.Where(itm => valueIds.Contains(itm.ID));
Это ужасно, иногда я действительно ненавижу обручи, которые заставляет EF прыгать, чтобы что-то делать. Но это работает, просто плохо смотрится в коде. Спасибо
Фактически, этот «обходной путь» берет все данные из базы данных и фильтрует их на C#. Если у вас много данных, это существенно снизит производительность.
-1: вы не хотите гидратировать коллекцию перед применением дополнительного фильтра.
В некоторых случаях для этого можно использовать метод расширения 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.
Какой тип
valueIds?