为什么这个查询会抛出异常?

5
我有一个名为User的表,其中有一个名为NxEnabledBIT NULL列,我无法更改。实际上,有些记录在该列中包含NULL
我不想在C#中使用可空类型,因此在投影中将其与true进行比较是有意义的(代码已简化,但这会生成相同的错误):
context.Users.Where(x => x.Id == 4)
             .Select(x => new 
                  { 
                      Id = x.Id,
                      Name = x.Name,
                      Enabled = x.NxEnabled == true
                  });

为什么这个查询在枚举时会抛出InvalidOperationException:将空值分配给System.Boolean类型的成员,该成员是非可空值类型。请注意,此处的查询更复杂,但where子句不是问题的原因。
3个回答

4
当您将true.IsEnabled字段进行比较时,LINQ to SQL将true作为查询中的参数传递。问题在于翻译将返回NULL:
SELECT [t0].[Id], [t0].[Name],
    (CASE 
        WHEN [t0].[NxEnabled] = @p0 THEN 1
        WHEN NOT ([t0].[NxEnabled] = @p0) THEN 0
        ELSE NULL
     END) AS [Enabled]
FROM [Users] AS [t0]

由于SQL92对于与NULL比较的定义方式,两个WHEN条件都是false。这在我的博客文章中有解释[免责声明:该文章属于我自己]。
使用Enabled = NxEnabled ?? false进行解决。

谢谢!我也长期遇到同样的问题。很奇怪C#表达式必须像SQL中的select子句一样处理空值。我得记住这个。 - symbiont

3

笔误 -- 您需要双等号 ==

.Where(x => x.Id == 4)

2
你应该将这个作为评论发布,以验证它是否真的是一个打字错误还是问题的源头。错误信息似乎并不是这样暗示的。 - ChrisF
1
那无法导致那个异常。 - istepaniuk

0
context.Users.Where(x => x.Id == 4)
             .Select(x => new Users()
                  { 
                      Id = x.Id,
                      Name = x.Name,
                      NxEnabled = x.NxEnabled ?? false
                  });

1
实际上,要与他的代码等效,应该是?? false。由于null不等于true,所以结果为false - Servy
?? null 毫无意义。如果是 null,就保持为 null?你需要的是 ?? false,正如我之前所说的。此答案还缺乏对为什么 OP 的代码不起作用的任何解释,因为他实际上有充分的理由认为它应该起作用。 - Servy
1
你现在又把它改回了 ?? true,这是错误的,正如我之前所说的。 - Servy
不,这是不正确的。它现在是可空的,但不应该是。 - Servy
@spajce,如果我这样做,NxEnabled 将会是 bool? 类型,这正是我想避免的。 - Alessandro D'Amario
我更新了答案。我相信那是正确的。请尝试测试 :) 以及如何使用 ?? 运算符 http://msdn.microsoft.com/en-us/library/ms173224.aspx - spajce

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