.Any()与Nullables - 当我期待真实时返回False

时间:2011-04-25 21:21:04

标签: c# linq extension-methods nullable

我有一个可以为null的视图模型...

public ObjectViewModel (){
    public int? Total
}

...我的数据库中有几行,总数为 null

尽管如此,这总是会返回 false

bool exists = repo.AllRows() // renamed this for clarity; returns IQueryable
                  .Any(r => r.Total == vm.Total); // I know r.Total and vm.Total
                                                  // are both null

但是以下内容返回 true (正如预期的那样):

bool exists = repo.All().Any(r => r.Total == null);

知道我在这里做错了吗?

5 个答案:

答案 0 :(得分:3)

假设你的意思是“vm.Total为null”而且All()是一个错字......

我认为您的问题是将其转换为SQL的方式:

  • 第一个查询被翻译为带有r.Total = @param1
  • 的WHERE子句
  • 使用IS NULL
  • 将第二个查询转换为WHERE子句

MSDN has a good description on NULL

  

值为NULL表示值为   未知。 NULL值不同   来自空值或零值。没有两个   空值相等。比较   在两个空值之间,或在一个之间   NULL和任何其他值,返回   未知因为每个NULL的值   不明。

这意味着你不能在SQL中使用比较运算符 - 因此你也不能在Linq中使用sql。

解决这个问题的方法有:

答案 1 :(得分:2)

Josh的回答似乎对我来说最准确。只需使用空合并运算符:

bool exists = repo.AllRows().Any(r => r.Total ?? 0 == vm.Total ?? 0);

...你不会再有一种“WHERE NULL = NULL”了,但是“WHERE 0 = 0”也没关系。

答案 2 :(得分:0)

正如Bala R所说,如果vm为null,那么你将无法访问Total属性,它必须抛出NullReferenceException。

您的查询应该是:

bool exists = repo.Any(r => r.Total == null);
如果exists属性中至少包含null的记录,

Total将为真。

答案 3 :(得分:0)

如果集合中的任何项目满足lambda指定的条件,则Any方法返回true。因此repo中的所有项都没有等于vm.Total的总数,但是有些项为null,所以第二个返回true。

要验证,在那里抛出一点调试代码,

Console.WriteLine("vm.Total=" + vm.Total.ToString());
foreach (var r in repo)
    Console.WriteLine("r.Total=" r.Total == null ? "null" : r.Total.ToString());

要看一下这些项目,您不应该看到等于r.Total的{​​{1}},并且您会看到至少一个vm.Total

答案 4 :(得分:0)

您的代码应该提供异常,但无论哪种方式都可以尝试:

Any(r => r.Total == vm==null ? null : vm.Total)