条件等于true且Nullable对象必须具有值的情况

时间:2018-10-11 08:24:19

标签: c# linq linq-to-sql where

我一直在寻找答案,但是找不到任何帮助我的东西。我收到此错误

  

可空对象必须具有一个值。

我的要求是:

from e in dc.tblElements 
where
    e.IsUnique &&
    (e.TypeID == 2) &&     
    (categoryId != null ? e.CategoryId.Value == categoryId.Value : true) &&
    ((e.Name.Contains(keyword)) ||
    (e.Keywords.Contains(keyword)))
select e

where条件的第三行是问题(categoryId)。如果categoryId有一个值,则它起作用,但当值为null时不起作用。但是,我用true代替了这一行,它也可以正常工作。我不明白这里出了什么问题。

表中的CategoryId可以为null,所以我尝试了:

(categoryId.HasValue && e.CategoryId.HasValue ? e.CategoryId.Value == categoryId.Value : true) 

我想做什么:我想根据where条件选择该表的所有元素。 categoryId来自下拉列表,因此,如果用户执行请求时仍选择默认值,则无论类别如何,我都希望显示所有元素。

4 个答案:

答案 0 :(得分:5)

仅比较两个变量就应该很好:

e.CategoryId == categoryId

如果您想对一个为NULL的特殊处理,也许是因为您希望这是NULL匹配一切而不是另一个NULL的特殊情况,您可以添加:

e.CategoryId == categoryId || !e.CategoryId.HasValue || !categoryId.HasValue

您对陈述的问题是您访问.Value。是的,如果您在内存中运行带有Linq-To-Objects的代码,那将是可行的,因为编译器将仅运行if语句的一个分支的代码(我知道是三元运算符,但是您明白了我的意思) 。但是对于数据库,需要准备一个语句。该语句必须完整存在,不使用任何短路。因此,语句生成器 将访问您的两个分支以为数据库构建该语句,并且其中一个分支将失败,因为它访问.Value尽管没有访问。

答案 1 :(得分:1)

好像您正在尝试实现“包罗万象” categoryId参数。这是SQL中的反模式和强烈的气味,可能导致性能下降。

在LINQ中,这不是必需的,因为您可以通过向查询中添加另一个.Where()调用来添加.Where()条件,例如:

var query = from e in dc.tblElements 
            where
                e.IsUnique &&
                e.TypeID == 2 &&     
                ( e.Name.Contains(keyword) ||
                  e.Keywords.Contains(keyword) )
            select e;
if (categoryId.HasValue)
{
    query=query.Where(e.CategoryId == categoryId);
}

您可以使用它在运行时添加多个条件

答案 2 :(得分:0)

将CategoryId设置为可为null的类型,然后尝试。

Nullable<int> CategoryId = null;

答案 3 :(得分:0)

尝试一下:

from e in dc.tblElements 
where
    e.IsUnique &&
    (e.TypeID == 2) &&     
    (categoryId.HasValue && e.CategoryId.Value == categoryId.Value) &&
    ((e.Name.Contains(keyword)) ||
    (e.Keywords.Contains(keyword)))
select e