Судя по форме вашего запроса, я считаю excludedRecords
списком целых чисел. Кроме того, поскольку вы помечаете LINQ to Entities, я принимаю results
за DbSet
в DbContext
.
Это проблема объединения локальных списков (excludedRecords
) с IQueryable
, ожидающим перевода в SQL (results
). Чтобы EF мог перевести полное выражение (ваш запрос) в SQL, он должен преобразовать этот локальный список в «что-то», что может быть частью оператора SQL. С помощью All()
и многих других операторов LINQ на основе наборов, а также при присоединении к локальному списку EF делает это, создавая временную таблицу (своего рода) из однострочных таблиц. Если в локальном списке всего 5 элементов, это выглядит так
SELECT ...
FROM [dbo].[Table] AS [Extent1]
WHERE EXISTS (SELECT
1 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]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]
UNION ALL
SELECT
4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]
UNION ALL
SELECT
5 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll4]
WHERE ([Extent1].[Id] = [UnionAll4].[C1]) OR (CASE WHEN ([Extent1].[Id] <> [UnionAll4].[C1]) THEN cast(1 as bit) WHEN ([Extent1].[Id] = [UnionAll4].[C1]) THEN cast(0 as bit) END IS NULL)
)
Несмотря на то, что потенциально это может привести к огромным SQL-запросам, это все же работает, когда локальный список не содержит «слишком много» элементов (скажем, до 1000).
Единственный оператор, который позволяет EF более эффективно использовать локальный список, — это Contains
. Contains
можно легко преобразовать в оператор SQL IN
. Если мы перепишем ваш запрос на эквивалент с Contains
, что также является ответом на ваш вопрос, ...
results = from q1 in results
where !excludedRecords.Contains(q1.ItemId)
select q1;
... SQL-запрос будет выглядеть так
SELECT ...
FROM [dbo].[Table] AS [Extent1]
WHERE NOT ([Extent1].[Id] IN (1, 2, 3, 4, 5))
Оператор IN
может обрабатывать больше элементов, чем эта «временная таблица», хотя это число все еще ограничено (возможно, 3000).
person
Gert Arnold
schedule
14.12.2013