VB.Net Linq to Entities 空值比较 - 'Is Nothing' 还是 '= Nothing'?

7
我们有几个使用.Net Framework 4和Linq to Entities的VB.Net项目。转向EF对我们来说是一个新的转变(使用了约4-6个月),因为我们可以更快地编写代码,得到了高层管理的支持。我们仍然使用很多存储过程,但我们甚至通过Linq to Entities执行这些存储过程。
我希望能够解决一些困惑,但我找不到一个直接的答案。我们有一些查询,我们想要记录某个特定字段具有NULL值。这些都是简单的选择查询,没有聚合或左连接等。Microsoft建议查询看起来像这样MSDN Link
dim query = from a in MyContext.MyTables
Where a.MyField = Nothing
Select a

我有几个项目都是这样做的,效果很好,在IDE中没有警告。最近另一个开发人员创建了一个新项目,当他像上面那样进行空值检查时,我们都会在IDE中收到以下警告:
警告1 这个表达式将始终评估为Nothing(由于从等号运算符的空传播)。要检查值是否为空,请考虑使用'Is Nothing'。
比较这些项目,每个项目都打开了选项显式和选项严格。如果我们忽略这个警告,在应用程序运行时我们得到了确切的记录集。如果我将=号更改为IS,则警告消失。但为什么在一个项目中出现了这个警告而在其他项目中却没有呢?即使在MSDN上也有使用等号运算符的例子,这让人感到困惑。

VB.NET LINQ也有Equals关键字。我没有测试的方法,但也许可以尝试一下这个?Where a.MyField Equals Nothing - Cᴏʀʏ
@Cory: 这是一个上下文关键字,仅在Join子句(据我所知)中使用。我认为你不能在任何其他地方使用它。 - Jeff Mercado
3个回答

6

生成列应该是 Nullable(Of T) 类型的。

这样你就可以像这样检查该字段是否有值:

dim query = from a in MyContext.MyTables
Where Not a.MyField.HasValue
Select a

我尝试在几种数据类型上使用它,但在字符串值上无法运行。我能够在可空整数、日期和布尔数据类型上使用HasValue成员。 - user1359018

2
我相信你在这里看到的是MyField是一个Nullable(Of T)类型。可能是原始的IntegerSingle等等...
你看到这个警告的原因是编译器将原始类型的普通等号运算符提升到Nullable(Of T)版本。它实际上执行以下操作。
Dim myField As Integer? = a.MyField
Dim other As Integer? = Nothing
If myField = other Then
 ...
End If

问题在于,当Integer?的值为Nothing时,它将不等于任何值。因此,上述的Where子句将始终返回False。编译器试图警告您这个有问题的Nullable(Of T)角落,并推动您进行一个Is Nothing检查,以确定a.MyField是否具有非空值。

这篇博客文章详细解释了为什么会产生这个警告以及所有相关机制。 这篇文章是用C#写的,但基本原则也适用于VB.Net。


所以如果我理解正确的话,等号在一个查询中有效是因为该字段不可为空,但在另一个查询中出现问题是因为它是可为空的,因此需要使用不同的语法。 - user1359018
@ChrisJones 正确。通常可以对可空值使用 =。但是,与 Nothing 进行比较将始终返回 False,因此编译器会发出警告。 - JaredPar
玩弄这个更多,我可以将可为空的字符串字段转换为= Nothing,但不能对其他数据类型进行操作,并且可以使用Afshin提到的Is Nothing或HasValue成员。感谢您对此进行了一些解释。 - user1359018

0

至少在LINQ to objects中,你可以使用这个代替:

Nullable(Of Integer).Equals(a, b)

这对于两个值中的任意一个或两个都为"Nothing"的情况都可以正常工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接