我一直在寻找答案,但是找不到任何帮助我的东西。我收到此错误
可空对象必须具有一个值。
我的要求是:
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来自下拉列表,因此,如果用户执行请求时仍选择默认值,则无论类别如何,我都希望显示所有元素。
答案 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