Эффективный способ запроса каждого элемента списка

Мне нужно выполнить итерацию по набору объектов (пусть это ID) и выполнить конкретный запрос для каждого из этих объектов. Например:

IEnumerable<int> ids = getIDs(); //[1,2,3,4...]

Сейчас у меня есть это решение:

DBEntities db = new DBEntities();

var results =
    from a in db.TABLEA
    join b in db.TABLEB on a.id equals b.id
    join c in db.TABLEC on b.oid equals c.oid
    where ids.Contains(c.id)
    select a; 

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

В идеале я хотел бы что-то вроде этого:

DBEntities db = new DBEntities();
(some data structure) ids = getIDs();

var results =
    from a in db.TABLEA
    join b in db.TABLEB on a.id equals b.id
    join c in db.TABLEC on b.oid equals c.oid
    join i in ids on c.id equals i.id;

В приведенном выше коде (псевдо) код будет перебирать мои элементы списка в одном запросе, делая это в одном запросе и выполняя мой фильтр каждым элементом списка.

Это способ сделать это? Если да, то какова соответствующая структура данных для реализации этого решения? Если нет, какие альтернативы у меня есть?

Ответ 1

Если это linq2Sql (или Linq2Entites), ваш единственный вариант, как в вашем примере 1. Вы не можете "присоединиться" к таблице со списком в памяти. Вы должны использовать Contains. Который будет переведен в запрос Where c.id IN(2,3,4,5,...) SQL

Ответ 2

Магнус отвечает верно, но не прав:)

Технически у вас есть два варианта в новых версиях Entity Framework (и я обнаружил это случайно). Contains, но также и Join.

Соединение с локальной последовательностью примитивных типов всегда было возможно, но очень быстро (после нескольких десятков элементов) поднял a SqlException:

Некоторая часть вашего оператора SQL вложен слишком глубоко. Перепишите запрос или разделите его на более мелкие запросы.

EF пытается перевести локальный список во временную таблицу в SQL. Это на удивление нетривиально. Он должен построить таблицу с помощью UNION -выбора операторов выбора, которые возвращают по 1 элемент каждый. Это то, к чему он привык, только с 5 элементами!

....
INNER JOIN  (SELECT 
    [UnionAll3].[C1] AS [C1]
    FROM  (SELECT 
        [UnionAll2].[C1] 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]
    UNION ALL
        SELECT 
        4 AS [C1]
        FROM  ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
UNION ALL
    SELECT 
    5 AS [C1]
    FROM  ( SELECT 1 AS X ) AS [SingleRowTable5]) AS [UnionAll4] ON ....

Как вы видите, если вы посмотрите внимательно, операторы UNION вложены. Уровень гнездования вскоре становится слишком глубоким, что делает этот подход практически бесполезным.

Однако в настоящее время SQL выглядит так:

....
INNER JOIN  (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] ON ....

Все еще не красота, но вложенность заменяется цепочкой, и список может содержать сотни элементов.

Но... (и именно поэтому ответ Магнуса верен), он не работает хорошо. Простой тест с 2000 элементами в списке занял 2,5 с Join и .25s с Contains. Таким образом, нет практического случая для соединения с локальной последовательностью.