生成的查询在实体框架的版本之间是不同的

Posted

技术标签:

【中文标题】生成的查询在实体框架的版本之间是不同的【英文标题】:Generated Query is different between versions of Entity Framework 【发布时间】:2017-01-01 01:45:34 【问题描述】:

我正在升级 Entity Framework 并已成功从 v5(但由于我们使用 .NET 4.0,程序集实际上是 v4.4)升级到最新版本的 v6。我们遇到了一个问题,即 EF5 和 EF6 以不同的方式生成相同的 IQueryable,从而产生不同的结果。

LINQ 查询是: Context.MyTable.SingleOrDefault(x => x.StringProperty != "");

在 EF5 中,SQL 如下所示(稍微简化):

SELECT TOP (2) ID AS ID, StringProperty AS StringProperty FROM MyTable WHERE N'' <> StringProperty

在 EF6 中,SQL 看起来像:

SELECT TOP (2) ID AS ID, StringProperty AS StringProperty FROM MyTable WHERE NOT((N'' = StringProperty) AND (StringProperty IS NOT NULL))

如果StringProperty 为空,EF5 查询不会返回该行,而 EF6 版本会。我没有在任何地方看到这个文档(不完全确定在哪里看)。这个例子很容易修复,虽然很难找到。有没有办法开启遗留行为?

更重要的是,我想知道是否有任何其他类似这样的更改,其中查询以不同的方式生成,从而导致不同的查询结果。是否有 EF6 中的重大更改列表?

【问题讨论】:

【参考方案1】:
> Is there a way to turn on the legacy behavior?

这篇 NULL value handling in Entity Framework 的帖子应该会有所帮助。

"DbContext.ContextOptions.UseCSharpNullComparisonBehavior 开关,当值可以为空时,它将自动将 NULL 比较逻辑嵌入到您的实体框架查询中"

“在 EF5 中,UseCSharpNullComparisonBehavior 标志默认为 false。EF6.0 引入了一项重大更改,其中标志默认为 true”

【讨论】:

我还没有尝试过,但它似乎正是我所需要的。从您发布的链接中,由于与 SQL 查询计划相关的性能原因,由于旧行为构建查询的方式,选择不使用索引,因此 EF6 默认值似乎是推荐值。未来的读者可能会注意到这一点。 我们先用代码,在语义上相同但相反。 DbContext.Configuration.UseDatabaseNullSematics = true 等价于 UseCSharpNullComparisonBehavior = false

以上是关于生成的查询在实体框架的版本之间是不同的的主要内容,如果未能解决你的问题,请参考以下文章

为啥实体框架会生成嵌套 SQL 查询?

实体框架使用 PatIndex 生成的查询不起作用

关联实体和非关联实体之间的连接,导致在 JPQL 中使用 Lazy fetch 生成非持久实体不断抛出 JpqlSyntaxException

实体框架生成单独的类

如何为实体框架 Sql 提供程序编写测试并访问生成的 Sql 命令

使用实体框架核心生成和访问存储过程