[英]Ef Core String Not Contains Excludes Null
Why is it that when i query in Entity Framework Core for string Not Equals it will give return NULL values (by appending "Or ISNULL(field)"), but when i query for example "not Contains" or "not StartWith" It will not为什么当我在 Entity Framework Core 中查询字符串 Not Equals 时,它会返回 NULL 值(通过附加“Or ISNULL(field)”),但是当我查询例如“not Contains”或“not StartWith”时它会不是
I know that i can achieve the same result by adding manually to the query to include NULL, my question is why are the 2 behaving differently when it comes to NULL?我知道我可以通过手动添加到查询中以包含 NULL 来获得相同的结果,我的问题是为什么 2 在涉及 NULL 时表现不同? is there any obvious reason for that?
有什么明显的原因吗?
Code Example:代码示例:
C# - dbContext.Employee.Where(x => x.jobNotes != "abc").Select(x => x.firstName).ToList();
C# -
dbContext.Employee.Where(x => x.jobNotes != "abc").Select(x => x.firstName).ToList();
Generated Sql - exec sp_executesql N'SELECT [x].[firstName] FROM [Employee] AS [x] WHERE (([x].[jobNotes] <> N''abc'') OR [x].[jobNotes] IS NULL)'
生成的 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();
C# -
dbContext.Employee.Where(x => !x.jobNotes.Contains("abc")).Select(x => x.firstName).ToList();
Generated Sql - exec sp_executesql N'SELECT [x].[firstName] FROM [Employee] AS [x] WHERE (CHARINDEX(N''abc'', [x].[jobNotes]) <= 0)'
生成的 Sql -
exec sp_executesql N'SELECT [x].[firstName] FROM [Employee] AS [x] WHERE (CHARINDEX(N''abc'', [x].[jobNotes]) <= 0)'
The reason is not "obviously", but it can be explained somehow:原因不是“显然”,但可以以某种方式解释:
Having the C# expression:有 C# 表达式:
x.jobNotes.Contains("abc")
only "works", when the value of x.JobNotes
is not NULL
, otherwise you would get a NullReferenceException
.只有“有效”,当
x.JobNotes
的值不是NULL
,否则你会得到一个NullReferenceException
。 To ensure that you don't, only NOT NULL
values are checked.为确保您不这样做,只检查
NOT NULL
值。 The generated SQL statement生成的 SQL 语句
(CHARINDEX(N''abc'', [x].[jobNotes]) <= 0)
does that because for any NULL
values in the jobNotes
table, the result of CHARINDEX
will be NULL
, as defined in the documentation of CHARINDEX
:这样做是因为对于
jobNotes
表中的任何NULL
值, CHARINDEX
的结果将是NULL
,如CHARINDEX
文档中所定义:
If either the expressionToFind or expressionToSearch expression has a NULL value, CHARINDEX returns NULL.
如果expressionToFind或expressionToSearch表达式具有 NULL 值,则 CHARINDEX 返回 NULL。
Comparing NULL
values in this case ( NULL <= 0
) results in UNKNOWN
, as defined in the documentations of comparison operators :在这种情况下比较
NULL
值 ( NULL <= 0
) 会导致UNKNOWN
,如比较运算符的文档中所定义:
When SET ANSI_NULLS is ON, an operator that has one or two NULL expressions returns UNKNOWN.
当 SET ANSI_NULLS 为 ON 时,具有一两个 NULL 表达式的运算符将返回 UNKNOWN。 When SET ANSI_NULLS is OFF, the same rules apply, except for the equals (=) and not equals (<>) operators.
当 SET ANSI_NULLS 为 OFF 时,应用相同的规则,但等于 (=) 和不等于 (<>) 运算符除外。 When SET ANSI_NULLS is OFF, these operators treat NULL as a known value, equivalent to any other NULL, and only return TRUE or FALSE (never UNKNOWN).
当 SET ANSI_NULLS 为 OFF 时,这些运算符将 NULL 视为已知值,等同于任何其他 NULL,并且只返回 TRUE 或 FALSE(从不为 UNKNOWN)。
I'm not sure what WHERE UNKNOWN
would do as you cannot run this expression directly, but as an example the expression WHERE NULL <= 0
results in WHERE FALSE
, which means the row with the jobNotes
column set to NULL
is not returned.我不确定
WHERE UNKNOWN
会做什么,因为您不能直接运行此表达式,但作为示例,表达式WHERE NULL <= 0
导致WHERE FALSE
,这意味着不会返回jobNotes
列设置为NULL
的行。
When you look at the query from the C# or Entity Framework standpoint, it does make sense that these NULL
values are not returned.当您从 C# 或实体框架的角度查看查询时,不返回这些
NULL
值确实是有意义的。 When you have a query like当您有类似的查询时
dbContext.Employee
.Where(x => !x.jobNotes.Contains("abc"))
.Select(x => x.firstName)
.ToList()
and you get entities where the jobNotes
column is NULL
, the question arise:并且您得到
jobNotes
NULL
实体,问题出现了:
"Wait, why is
jobNotes
NULL? It should have thrown aNullReferenceException
because of theContains()
method call."“等等,为什么
jobNotes
NULL?它应该因为Contains()
方法调用而抛出NullReferenceException
。”
So, that might be the reason why it does not return rows where the jobNotes
column has the value NULL
(and works "differently" with x.jobNotes != "abc"
).因此,这可能是它不返回
jobNotes
列值为NULL
行的原因(并且与x.jobNotes != "abc"
以“不同的方式”工作)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.