Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 其中条件等于true且可为null的对象必须有一个值_C#_Linq_Linq To Sql_Where - Fatal编程技术网

C# 其中条件等于true且可为null的对象必须有一个值

C# 其中条件等于true且可为null的对象必须有一个值,c#,linq,linq-to-sql,where,C#,Linq,Linq To Sql,Where,我一直在寻找答案,但找不到任何帮助。我得到这个错误 可为null的对象必须有一个值 我的要求是: from e in dc.tblElements where e.IsUnique && (e.TypeID == 2) && (categoryId != null ? e.CategoryId.Value == categoryId.Value : true) && ((e.Name.Contains(k

我一直在寻找答案,但找不到任何帮助。我得到这个错误

可为null的对象必须有一个值

我的要求是:

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
的第三行,其中
条件是问题(
类别ID
)。如果
categoryId
有一个值,则该值有效,但在
null
时无效。但是,我将这一行替换为
true
,它也可以工作。我不明白这里有什么问题

在我的表中,CategoryId可以为null,因此我尝试:

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

我想做的是:我想根据where条件选择这个表的所有元素。categoryId来自一个下拉列表,因此,如果在用户执行请求时仍选择了默认值,则我希望显示所有元素,而不管类别是什么。

您应该善于比较两个变量:

e.CategoryId == categoryId
如果您希望对其中一个为NULL进行特殊处理,可能是因为您希望这是一个NULL匹配所有内容而不是另一个NULL的特殊情况,您可以添加:

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


您的语句的问题在于您访问
.Value
。是的,如果您使用Linq To对象在内存中运行代码,它会工作,因为编译器只会运行if语句的一个分支的代码(三元运算符,我知道,但您明白我的意思)。但是对于数据库,需要准备一个语句。该语句需要完整,它不使用任何短路。因此,语句生成器将访问您的两个分支来为数据库构建该语句,其中一个分支将失败,因为它访问
.Value
,尽管没有任何值。

将CategoryId设为可空类型,然后重试

Nullable<int> CategoryId = null;
Nullable CategoryId=null;

看起来您正在尝试实现一个“catch all”
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);
}
您可以使用此选项在运行时添加多个条件

尝试以下操作:

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

你不需要那条线。LINQ中不需要“catch all”参数,您可以根据需要添加另一个
Where()
子句。您能用简单的英语描述一下您想要什么吗?我编辑了主题。@Panagiotis Kanavos您能再解释一下您的想法吗?在您的案例中(第二行),如果categoryId=5,我会得到categoryId=5的所有元素,但也会得到没有类别的所有元素。当categoryId有值时,我只想要有这个categoryId的元素。对吗?@Tylerduden我不能告诉你你想要什么。这就是为什么我在对你的问题的评论中问你。如果你能描述你想要发生什么,我们可以帮助你u与之匹配。@nvoigt如果这是SQL,它将是捕获所有参数的反模式。如果
categoryId
为空,正确的选择是根本不添加条件。@nvoigt好的,我想,我理解你的意思。谢谢你的回复和解释。我通过
((categoryId.HasValue)?(p.categoryId==categoryId)更改了行:正确)
而且它工作起来很有魅力。@Tylerduden最好先检查性能。查询优化器将缓存用于第一次执行的计划。如果第一次执行有null CategoryID参数,它可能不会使用任何包含
CategoryID
的索引。这可能会损害具有非null CategoryID的调用的性能参数,例如对包含CategoryID的Index执行表扫描而不是搜索