我必须遍历一组对象(比如说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列表小于我搜索的表格。话虽这么说,上面的解决方案看起来效率低下,因为当我想要相反时,我正在寻找我的表中的每个记录与较小的列表。我也不想遍历列表,并且一次执行一个元素的查询。
理想情况下,我想要这样的事情:
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;
上面的(伪)代码将在一个查询中迭代我的列表元素,在单个查询中执行,并按列表的每个元素执行我的过滤器。
这是这样做的吗?如果是这样,实施此解决方案的适当数据结构是什么?如果没有,我有哪些替代方案?
答案 0 :(得分:3)
如果这是linq2Sql(或Linq2Entites),您的唯一选择就像您的示例中一样1.您无法“加入”具有内存列表的表。您必须使用Contains
。哪个将被翻译为
Where c.id IN(2,3,4,5,...)
SQL查询
答案 1 :(得分:3)
马格努斯的回答是对的,但不对::)
技术上在较新版本的Entity Framework中你有两个选项(我偶然发现了这个)。 Contains
当然,还有Join
。
加入一个本地类型的原始类型一直是可能的,但很快(在几十个元素之后)引发SqlException
:
SQL语句的某些部分嵌套太深。重写查询或将其分解为较小的查询。
EF尝试将本地列表转换为SQL中的临时表。这是非常重要的。它必须通过UNION
构建表,每个返回1个元素的select语句。这就是它过去只有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个元素的简单测试使用join
获得2.5秒,使用Contains
获得.25s。因此,加入本地序列仍然没有实际案例。