【发布时间】:2015-04-08 12:38:06
【问题描述】:
我正在使用 EF6,我想获取一组 ID 中的表中的记录。
例如,在我的测试中,我使用了 4 个 ID。
我尝试了两个选项,第一个是任何选项。
dbContext.MyTable
.Where(x => myIDS.Any(y=> y == x.MyID));
而这个 linq 表达式生成的 T-SQL 是:
SELECT
*
FROM [dbo].[MiTabla] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM (SELECT
[UnionAll2].[C1] AS [C1]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
cast(130 as bigint) AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
cast(139 as bigint) AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
cast(140 as bigint) AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
UNION ALL
SELECT
cast(141 as bigint) AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]) AS [UnionAll3]
WHERE [UnionAll3].[C1] = [Extent1].[MiID]
)
可以看出,T-SQL 是一个“存在的地方”,它使用了许多子查询和联合。
第二个选项是包含。
dbContext.MyTable
.Where(x => myIDS.Contains(x.MiID));
还有 T-SQL:
SELECT
*
FROM [dbo].[MiTabla] AS [Extent1]
WHERE [Extent1].[MiID] IN (cast(130 as bigint), cast(139 as bigint), cast(140 as bigint), cast(141 as bigint))
包含被翻译成“在哪里”,但查询要简单得多。
我读过 any 它曾经更快,所以我怀疑 any 虽然乍一看更复杂,但是否更快。
非常感谢。
编辑:我有一些测试(我不知道这是否是测试的最佳方法)。
System.Diagnostics.Stopwatch miswContains = new System.Diagnostics.Stopwatch();
miswContains.Start();
for (int i = 0; i < 100; i++)
{
IQueryable<MyTable> iq = dbContext.MyTable
.Where(x => myIDS.Contains(x.MyID));
iq.ToArrayAsync();
}
miswContains.Stop();
System.Diagnostics.Stopwatch miswAny = new System.Diagnostics.Stopwatch();
miswAny.Start();
for (int i = 0; i < 20; i++)
{
IQueryable<MyTable> iq = dbContext.Mytable
.Where(x => myIDS.Any(y => y == x.MyID));
iq.ToArrayAsync();
}
miswAny.Stop();
结果是miswAny大约是850ms,miswContains大约是4251ms。
所以第二个选项,带有 contaions,速度较慢。
【问题讨论】:
-
Entity Framework生成了带有select *的代码?类型的 ID 是否长?你怎么知道结果是否没有缓存,你是否尝试交换查询顺序?
标签: c# entity-framework