gpt4 book ai didi

C# lambda 表达式常量与字符串

转载 作者:太空狗 更新时间:2023-10-30 01:16:08 26 4
gpt4 key购买 nike

如果我运行这个表达式,有人可以解释为什么吗:

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 的应用效率很低(返回需要一分钟以上)。

编辑 2:

我看到的数据库中的跟踪查询:

用常量调用时:

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 测试导致全表扫描...

最佳答案

理论#1

如果您已经测试了生成的查询并确定它实际上是导致全表扫描的参数 null 检查,那么修复非常简单:

NameDbContext.Configuration.UseDatabaseNullSemantics = true;

这将导致简化的 WHERE 子句:

WHERE "Extent2"."LAST_NAME" = :p__linq__0

显然,您需要考虑这对使用 NameDbContext 的其他查询的影响。

或者,您可以使用@IanMercer 的非常有趣的解决方案并执行表达式树节点替换以获得所需的 WHERE 子句。我希望最终结果是相似的,尽管我不确定 Oracle 是否足够聪明,可以在没有显式参数化的情况下生成可重用的查询计划,这可能会导致一些重新编译开销。

理论 #2

根据个人经验(虽然是使用 SQL Server,但由于一般概念是相同的,我会假设这适用于您的情况)绕过索引可能还有另一个原因,那就是您的 之间的类型不匹配LAST_NAME 列和 :p__linq__0 参数。在我的场景中,数据库中的列是非 unicode,但 EF 生成的参数是 unicode(varcharnvarchar 分别 - unicode 是 EF 的默认值),使得索引查找是不可能的。

关于C# lambda 表达式常量与字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36414150/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com