首页 > 解决方案 > Ef 核心字符串不包含排除 Null

问题描述

为什么当我在 Entity Framework Core 中查询字符串 Not Equals 时它会返回 NULL 值(通过附加“或 ISNULL(字段)”),但是当我查询例如“不包含”或“不 StartWith”时它会不是

我知道我可以通过手动添加到查询中以包含 NULL 来获得相同的结果,我的问题是为什么 2 在涉及 NULL 时表现不同?有什么明显的原因吗?

代码示例:

C# -dbContext.Employee.Where(x => x.jobNotes != "abc").Select(x => x.firstName).ToList();

生成的 Sql -exec sp_executesql N'SELECT [x].[firstName] FROM [Employee] AS [x] WHERE (([x].[jobNotes] <> N''abc'') OR [x].[jobNotes] IS NULL)'

C# -dbContext.Employee.Where(x => !x.jobNotes.Contains("abc")).Select(x => x.firstName).ToList();

生成的 Sql -exec sp_executesql N'SELECT [x].[firstName] FROM [Employee] AS [x] WHERE (CHARINDEX(N''abc'', [x].[jobNotes]) <= 0)'

标签: c#entity-framework-core

解决方案


原因不是“明显”,但可以通过某种方式解释:

具有 C# 表达式:

x.jobNotes.Contains("abc")

只有“有效”,当 的值x.JobNotes不是时NULL,否则你会得到一个NullReferenceException. 为确保您不这样做,仅NOT NULL检查值。生成的 SQL 语句

(CHARINDEX(N''abc'', [x].[jobNotes]) <= 0)

这样做是因为对于表NULL中的任何值jobNotes,结果CHARINDEX将是NULL,如以下文档中CHARINDEX所定义:

如果expressionToFindexpressionToSearch表达式具有 NULL 值,则 CHARINDEX 返回 NULL。

在这种情况下比较NULL值 ( NULL <= 0) 会导致,如比较运算符UNKNOWN的文档中所定义:

当 SET ANSI_NULLS 为 ON 时,具有一个或两个 NULL 表达式的运算符返回 UNKNOWN。当 SET ANSI_NULLS 为 OFF 时,应用相同的规则,但等于 (=) 和不等于 (<>) 运算符除外。当 SET ANSI_NULLS 为 OFF 时,这些运算符将 NULL 视为已知值,等同于任何其他 NULL,并且仅返回 TRUE 或 FALSE(从不 UNKNOWN)。

我不确定该怎么WHERE UNKNOWN做,因为您不能直接运行此表达式,但作为示例,表达式WHERE NULL <= 0导致WHERE FALSE,这意味着不返回jobNotes列设置为的行。NULL

NULL当您从 C# 或实体框架的角度查看查询时,不返回这些值是有道理的。当您有类似的查询时

dbContext.Employee
    .Where(x => !x.jobNotes.Contains("abc"))
    .Select(x => x.firstName)
    .ToList()

jobNotes并且您获得了该列所在的实体NULL,问题就出现了:

“等等,为什么是jobNotesNULL?它应该NullReferenceException因为Contains()方法调用而抛出一个。”

因此,这可能是它不返回该jobNotes列具有值的行的原因NULL(并且与“不同”工作x.jobNotes != "abc")。


推荐阅读