为什么 EF 比较空变量时不返回任何结果?

3

我在使用Entity Framework中的数据上下文选择数据时遇到了问题,经过排查,发现是查询null值的问题。我的方法如下:

public void DoStuff(int? someInt)
{
    var someData = dataContext.MyEntities.Where(x => x.SomeProperty == someInt);
    // someData always yields no results if someInt is null, even though
    // there are rows in the table that have null for that column.
}

如果someInt为空,则上述方法会失败。但是这行代码可以正常运行:
var someData = dataContext.MyEntities.Where(x => x.SomeProperty == null);

为什么我在第二个中获得数据,而在第一个中却没有?

1
尝试使用 someInt.Value。可空类型实际上并不为 null,但其值为 null。 - Erik Funkenbusch
@MystereMan,我刚刚测试了一下。请看Ryan Bennett的回答评论。虽然你的想法很好。 - Chev
1
@MystereMan 语义上来说,它空的 - 并且说“它的值是”是不正确的:一个空的可null类型 没有 值,因此思考这种不存在的值的本质是毫无意义的。 - Marc Gravell
1
@MystereMan 不行,因为 int?.Valueint 类型,不能为 null。 - Chev
@Mystere 不是这样的,它会抛出一个异常。你可以试一下。 - Marc Gravell
显示剩余2条评论
2个回答

6

我猜测,它正在生成并使用一种SQL查询形式,该形式期望非空值:

where x.SomeProperty = @param

不是使用SQL来展示C#的空值相等语义:

where x.SomeProperty is null

这里的关键点是在C#中,null等于null;在ANSI-SQL中,null既不等于null也不(令人困惑地)不等于null - 需要使用不同的语法来测试null。
我曾经看到LINQ-to-SQL做了同样的事情,并且认为这是违反直觉的。我唯一的建议是:自己测试候选参数是否为null,并进行常量/字面量 == null 测试。如果你喜欢表达式树,它也可能通过检查和重写表达式树来完成相同的工作,但特殊处理null更简单。

是的,你可能无法避免对 someInt 进行空值检查。同意。 - Ryan Bennett
1
@Alex,个人而言,我会用另一种方式来做:if(foo==null) query = query.Where(x=>x.Foo==null) else query = query.Where(x=>x.Foo==foo),但无论哪种方法都可以。 - Marc Gravell
@AlexFord - 我可能会这样做:.Where(x => x.SomeProperty == someInt ?? null)(我知道,这是使用空合并的一种古怪方式,但我认为它应该可以工作)。 - Erik Funkenbusch
有什么特别的原因吗?我只喜欢我的代码因为它只有一行而且不太长。 - Chev
@MystereMan 哦,看起来不错。让我测试一下。 - Chev
显示剩余4条评论

0

someInt本身不是null。someInt.Value将为null。


我刚刚测试了一下。.Where(x => x.SomeProperty == someInt.Value) 仍然没有返回结果。.Where(x => x.SomeProperty.Value == someInt.Value) 也没有返回结果。 - Chev
4
someInt.Value不能为null,因为它被声明为int,而int永远不会是null。 - recursive
1
今天学到了一些东西。谢谢 - Ryan Bennett

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