【发布时间】:2016-04-04 22:39:49
【问题描述】:
如果我运行这个表达式,有人可以解释为什么:
const string testValue = "ABC";
return NameDbContext.MasterNames
.Where(m => m.Names.Any(n => n.LastName == testValue))
.ToList();
我得到了预期的结果,但是如果我使用 testValue 作为变量运行相同的结果,它会失败:
string testValue = "ABC";
return NameDbContext.MasterNames
.Where(m => m.Names.Any(n => n.LastName == testValue))
.ToList();
这似乎只发生在string 上。与int 类似的代码在将testValue 作为变量或常量都可以正常工作。
我怀疑这是由于字符串的对象性质。如果是这种情况,我怎么能用变量调用这个表达式(我不知道编译时testValue 的值)。
谢谢。
编辑:
此查询针对大型 oracle 数据表(> 600 万行)运行。使用常量时,它会立即返回正确的结果集。使用变量运行时,似乎where 的应用效率非常低(返回需要一分钟以上)。
EDIT2:
在我看到的数据库中跟踪查询:
使用常量调用时:
SELECT *
FROM (SELECT "Filter2"."MALPHA_KEY" AS "MALPHA_KEY"
FROM (SELECT "Extent1"."MALPHA_KEY" AS "MALPHA_KEY",
ROW_NUMBER () OVER (ORDER BY "Extent1"."MALPHA_KEY" ASC)
AS "row_number"
FROM "RMS"."ALPHA_MASTER_NAME" "Extent1"
WHERE (EXISTS (
SELECT 1 AS "C1"
FROM "RMS"."ALPHA" "Extent2"
WHERE ( ("Extent1"."MALPHA_KEY" =
"Extent2"."MALPHA_KEY"
)
AND ('ABC' = "Extent2"."LAST_NAME")
))
)) "Filter2"
WHERE ("Filter2"."row_number" > 0)
ORDER BY "Filter2"."MALPHA_KEY" ASC)
WHERE (ROWNUM <= (50))
使用变量调用时:
SELECT *
FROM (SELECT "Project2"."MALPHA_KEY" AS "MALPHA_KEY"
FROM (SELECT "Project2"."MALPHA_KEY" AS "MALPHA_KEY",
ROW_NUMBER () OVER (ORDER BY "Project2"."MALPHA_KEY" ASC)
AS "row_number"
FROM (SELECT "Extent1"."MALPHA_KEY" AS "MALPHA_KEY"
FROM "RMS"."ALPHA_MASTER_NAME" "Extent1"
WHERE (EXISTS (
SELECT 1 AS "C1"
FROM "RMS"."ALPHA" "Extent2"
WHERE ( ("Extent1"."MALPHA_KEY" =
"Extent2"."MALPHA_KEY"
)
AND ( ("Extent2"."LAST_NAME" =
:p__linq__0
)
OR ( ("Extent2"."LAST_NAME" IS NULL
)
AND (:p__linq__0 IS NULL
)
)
)
))
)) "Project2") "Project2"
WHERE ("Project2"."row_number" > 0)
ORDER BY "Project2"."MALPHA_KEY" ASC)
WHERE (ROWNUM <= (50))
注意 where 语句的区别(除了使用变量)它测试 NULL 相等性
AND ( ("Extent2"."LAST_NAME" = :p__linq__0
)
OR ( ("Extent2"."LAST_NAME" IS NULL )
AND (:p__linq__0 IS NULL ) ) )
对 NULL 的测试导致全表扫描...
【问题讨论】:
-
试试((n => n.LastName.Equals(testValue)),看看有没有区别。
-
“失败”是什么意思?
-
请解释什么失败,你得到什么样的错误?
-
@Bibi,看起来不错,我们正在取得进展。首先要尝试:
DbContext.Configuration.UseDatabaseNullSemantics = true将导致第二个查询生成更接近“const”版本的 WHERE 子句。如果之后还是很慢,很可能是参数数据类型不匹配(:p__linq__0)。 -
@Bibi,这正是打开
UseDatabaseNullSemantics所做的事情:它强制使用直接的WHERE xxx = @param子句,而无需额外的空检查。
标签: c# linq lambda where-clause