查询列表中每个元素的有效方法

Efficient way to query each element of a list

我必须遍历一组对象(比方说 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; 

但请记住,ID 列表小于我正在搜索的 table。话虽这么说,上面的解决方案似乎效率低下,因为当我想要相反的时候,我正在寻找我的 table 的每条记录对一个较小的列表。我也不想遍历列表,一次只对一个元素执行查询。

理想情况下,我想要这样的东西:

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;

上面的(伪)代码将在单个查询中迭代我的列表元素,在单个查询中执行此操作并按列表的每个元素执行我的过滤器。

是这样吗?如果是这样,实施该解决方案的适当数据结构是什么?如果没有,我有哪些选择?

如果这是 linq2Sql(或 Linq2Entites),您唯一的选择就是在您的示例 1 中。您不能 "join" 具有内存列表的 table。你必须使用 Contains。这将被翻译成
Where c.id IN(2,3,4,5,...) SQL 查询

Magnus 的回答是正确的但不正确:)

技术上 在 Entity Framework 的较新版本中您确实有两个选项(我偶然发现了这一点)。 Contains 当然还有 Join.

加入原始类型的本地序列一直是可能的,但很快(在几十个元素之后)引发了 SqlException:

Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.

EF 尝试将本地列表转换为 SQL 中的临时列表 table。令人惊讶的是,这并不平凡。它必须通过 UNION-ing select 语句构建 table,每个 return 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 ....

仍然不是很漂亮,但是嵌套被链式取代并且列表可以包含数百个元素。

但是...(这就是为什么 Magnus 的回答是正确的),它表现不佳。列表中包含 2000 个元素的简单测试使用 join 花费了 2.5 秒,使用 Contains 花费了 .25 秒。所以仍然没有用本地序列连接的实际案例。