【问题标题】:Entity Framework Core Where clauseEntity Framework Core Where 子句
【发布时间】:2021-06-24 05:11:59
【问题描述】:

我正在使用 Entity Framework Core 来查询视图。我可以将 where 子句添加到视图中的列,但是当向一个特定列添加子句时,它似乎正在添加空检查。

实体框架核心版本:3.1.4

例子:

var query = _appContext.MyView.AsQueryable();
query = query.Where(d => d.field1 != d.field2);

这会产生这样的结果:

Expression = {value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[DAL.Models.MyView]).
WHERE ((([e].[field1] <> [e].[field2]) OR ([e].[field1] IS NULL OR [e].[field2] IS NULL)) AND ([e].[field1] IS NOT NULL OR [e].[field2] IS NOT NULL)) 

但它应该只是:

WHERE ([e].[field1] <> [e].[field2])

【问题讨论】:

  • 我假设这两个字段都可以为空?如果是这样,query = query.Where(d =&gt; d.field1.Value != d.field2.Value);
  • 是的,这两个字段都可以为空。我尝试将 .value 添加到具有相同结果的两个字段。我以前使用的是 dbml 文件,并且相同的代码有效。我不确定为什么现在要添加空检查。
  • @Dennis 您使用的是哪个数据库,field1field2 的确切类型是什么?

标签: c# entity-framework-core


【解决方案1】:

问题在于将一个值与 NULL 进行比较将导致 NULL(取决于所使用的数据库和运算符)。例如,MySQL 文档12.3 Type Conversion in Expression Evaluation 说:

如果一个或两个参数为NULL,则比较结果为NULL,但NULL-safe &lt;=&gt; 相等比较运算符除外。对于NULL &lt;=&gt; NULL,结果为true。无需转换。

但是当你有WHERE NULL 为一行时,它不会被包括在内。这可能意味着当您比较 'abc' != NULL 时,即使 'abc'NULL 的值不同,您也不会得到这一行。

假设你有下表:

mysql> SELECT * FROM foobar;
+----+--------+--------+
| id | field1 | field2 |
+----+--------+--------+
|  1 | NULL   | NULL   |
|  2 | NULL   | a      |
|  3 | a      | a      |
|  4 | b      | a      |
|  5 | b      | NULL   |
+----+--------+--------+
5 rows in set (0.00 sec)

当您运行一个简单的field1 != field2 条件时,您得到的行数比预期的要少(从原始 C# 代码,而不是从数据库的角度来看):

mysql> SELECT * FROM foobar WHERE field1 != field2;
+----+--------+--------+
| id | field1 | field2 |
+----+--------+--------+
|  4 | b      | a      |
+----+--------+--------+

如您所见,ID 为25 的行没有返回。为了同时获取这些行,EF Core 将添加额外的检查/运算符来获取您期望的所有行:

mysql> SELECT * FROM foobar WHERE ((field1 != field2 OR field1 IS NULL OR field2 IS NULL) AND (field1 IS NOT NULL OR field2 IS NOT NULL));
+----+--------+--------+
| id | field1 | field2 |
+----+--------+--------+
|  2 | NULL   | a      |
|  4 | b      | a      |
|  5 | b      | NULL   |
+----+--------+--------+
3 rows in set (0.00 sec)

所以,EF Core 会生成这种查询是正确的。

【讨论】:

    【解决方案2】:

    官方文档中清楚地描述了这种情况以及如何禁用它:https://docs.microsoft.com/en-us/ef/core/querying/null-comparisons

    optionsBuilder.UseRelationalNulls();
    

    【讨论】:

      【解决方案3】:

      Core 的行为似乎与使用 enfityframework(dbml 文件)不同。你必须先检查一个我以前不需要做的值。

      这行得通。 代码: query = query.Where(d => ((d.​​field1.HasValue && d.field2.HasValue) && d.field1!= d.field2.Value));

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-05-07
        • 1970-01-01
        • 1970-01-01
        • 2020-01-28
        • 2019-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多