【问题标题】:Why EF6 LINQ does not generate proper "is null" SQL for null string variable comparison?为什么 EF6 LINQ 不为空字符串变量比较生成正确的“为空”SQL?
【发布时间】:2020-02-20 10:28:25
【问题描述】:

我们有一个基于 EDMX 的 EF6 应用程序,我们想在其中运行这样的 LINQ 查询。

string category = ... // comes from somewhere and equals to null
context.Product.Where(e => e.Category == category).ToArray();

我看到的问题是生成的 SQL 在 where 子句中包含一个 [table].[Category] = @p...,而不管变量 category 是否为 null。因此,如果变量为 null,则查询最终不会返回任何结果,而不是生成正确的 is null 条件并返回正确的行。

我已经使用显式 e => e.Category == null 表达式进行了测试,并且确实按预期生成了 is null

我还检查了 EDMX 和 SQL,对应的 Category 列在这两个地方都可以为空,所以这可能不是问题。

任何帮助将不胜感激。

【问题讨论】:

  • 您有什么理由不在 LINQ 端进行 null 检查吗?我的意思是,你不能只有一个 WHERE 语句。你知道你可以链接他们,也动态?我的标准基本上是做空检查,然后只在 t 不为空时添加 where 子句。否则这看起来像一个错误 - 在 github 端打开票证。至少它们应该生成 IS NULL。
  • 预期是错误的,会违反 SQL 的三值逻辑,实际上惊讶 开发人员希望 null 值什么也不返回。正如您发布的那样,EF(和大多数 ORM)生成参数化查询。每次 value 更改时,查询都不会更改。
  • Category = @p1Category = @p1 or Category IS NULL 也有很大不同,导致执行计划和性能非常不同。 EF(或任何 ORM)不能随意选择更宽的查询而不是更窄的查询,因为它会返回 un 预期的结果并导致性能更差。您可能会争辩说,对于那些期望 ORM 使用 SQL 语义的人来说,应该有一个开关,但是当 其他 开发人员试图理解为什么查询不符合预期
  • @PanagiotisKanavos 感谢您的澄清,这是有道理的。然而,我所期望的是 EF 是 聪明的,因此它会在解析我的 LINQ 表达式时注意到表达式 category 基本上是 null 所以它应该生成一个 [Category] is null where 子句这个案例。似乎 EF 不会在本地评估此类表达式,而只是生成参数化查询。
  • @ZoltánTamási 我希望 EF(或 any ORM) 违反 SQL 的行为。您要求 EF 使用 C# 的 NULL 逻辑而不是 SQL,即使它显然是在查询 SQL 数据库。

标签: c# entity-framework-6 linq-to-entities


【解决方案1】:

尝试将context.Configuration.UseDatabaseNullSemantics 设置为false。这是影响上述行为的属性。

查看文档here

【讨论】:

    猜你喜欢
    • 2020-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 1970-01-01
    • 2018-07-15
    • 2020-04-30
    • 2017-07-20
    相关资源
    最近更新 更多