C# 在linq查询中处理可为null的bool
我有一种情况,我将null bool传递给方法,然后在linq查询中,如果该参数为null,那么我需要获取所有记录,否则进行比较并返回相对值 以下是我尝试过的(将方法简化为只问相关问题)C# 在linq查询中处理可为null的bool,c#,linq,C#,Linq,我有一种情况,我将null bool传递给方法,然后在linq查询中,如果该参数为null,那么我需要获取所有记录,否则进行比较并返回相对值 以下是我尝试过的(将方法简化为只问相关问题) 公共列表获取(bool?allocated=null){ 返回(从DbContext.Something中的x返回) 其中x.Active&(allocated==null | | x.allocated==allocated.Value) 选择x).ToList(); } 我还检查了是否分配了HasValu
公共列表获取(bool?allocated=null){
返回(从DbContext.Something中的x返回)
其中x.Active&(allocated==null | | x.allocated==allocated.Value)
选择x).ToList();
}
我还检查了是否分配了HasValue
,但每次都会出现相同的问题
我得到的例外是:
System.InvalidOperationException:“可为null的对象必须有一个值。”
我现在还不清楚为什么会失败,但是当我遇到这样的问题时,我倾向于简化查询。特别是,“表达式树到SQL”转换代码所做的工作越少,就越有可能工作 假设
allocated==null
不会在查询过程中更改,我会尝试将代码更改为仅有条件地查询该部分
public List<Something> Fetch(bool? allocated = null)
{
var query = DbContext.Something.Where(x => x.Active);
if (allocated != null)
{
// Do this outside the lambda expression, so it's just bool in the expression tree
bool allocatedValue = allocated.Value;
query = query.Where(x => x.Allocated == allocatedValue);
}
return query.ToList();
}
公共列表获取(bool?allocated=null)
{
var query=DbContext.Something.Where(x=>x.Active);
如果(已分配!=null)
{
//在lambda表达式之外执行此操作,因此它只是表达式树中的布尔
bool allocatedValue=已分配的.Value;
query=query.Where(x=>x.Allocated==allocatedValue);
}
返回query.ToList();
}
投票支持Jon Skeet的回答
但有一些解释说明了为什么会发生这种情况,
Linq处理空值没有问题
但是LINQtoSQL或LINQtoEntities(EF)投影的行为会有所不同!不确定是bug还是特性,但无法转换为t-SQL。
谷歌搜索:LINQtoEntities或LINQtoSQL比较可空类型以获得答案
为了避免无法转换为T-SQL的NULL=1比较,我通常这样做
var allocated = (bool?)null;
public List<Something> Fetch(bool? allocated = null){
if(allocated != null)
{
allocated = allocated.Value;
}
return (from x in DbContext.Something
where x.Active && (allocated == null || x.Allocated == allocated)
select x).ToList();
}
这对默认为“null”的方法可选参数不起作用
证明以下观点的小型试验:
private void MyTest()
{
var result = FetchListLinq(true);
result = FetchDbContextLinq(true);
result = FetchListLinq();
result = FetchDbContextLinq();
}
private List<object> FetchListLinq(bool? allocated = null)
{
var myList = new List<dynamic>() { new { Id = 1, Allocated = true, Active = true }, new { Id = 2, Allocated = false, Active = true }, new { Id = 3, Allocated = true, Active = false } };
return (from x in myList
where x.Active && (allocated == null || x.Allocated == allocated.Value)
select x).ToList();
}
private List<object> FetchDbContextLinq(bool? allocated = null)
{
// allocated = allocated ?? (bool?)null; // fix for Linq to SQL or Linq to Entity
var notWorking = (from x in DbContext.Something
where x.Active && (allocated == null || x.Allocated == allocated.Value)
select x).ToList();
}
private void MyTest()
{
var result=FetchListLinq(true);
结果=FetchDbContextLinq(真);
结果=FetchListLinq();
结果=FetchDbContextLinq();
}
私有列表FetchListLinq(bool?allocated=null)
{
var myList=new List(){new{Id=1,Allocated=true,Active=true},new{Id=2,Allocated=false,Active=true},new{Id=3,Allocated=true,Active=false};
返回(从myList中的x开始)
其中x.Active&(allocated==null | | x.allocated==allocated.Value)
选择x).ToList();
}
私有列表FetchDbContextLinq(bool?allocated=null)
{
//已分配=已分配???(bool?)null;//修复Linq到SQL或Linq到实体
var notWorking=(来自DbContext.Something中的x
其中x.Active&(allocated==null | | x.allocated==allocated.Value)
选择x).ToList();
}
不要像约翰·斯基特(John skeet)中提到的那样单独使用where子句,而是简单地这样做
var allocated = (bool?)null;
public List<Something> Fetch(bool? allocated = null){
if(allocated != null)
{
allocated = allocated.Value;
}
return (from x in DbContext.Something
where x.Active && (allocated == null || x.Allocated == allocated)
select x).ToList();
}
公共列表获取(bool?allocated=null){
如果(已分配!=null)
{
已分配=已分配。值;
}
返回(从DbContext.Something中的x返回)
其中x.Active&(allocated==null | | x.allocated==allocated)
选择x).ToList();
}
我查过了。它工作正常 我假设这是一个异常而不是编译时错误?请提供更多详细信息,最好是堆栈跟踪,当然还有异常类型。知道
x.Allocated
的类型也很好。是的,它是例外。将更新问题。而x.Allocated也是boolI希望在同一where子句中有一个解决方案。但由于这一点对其他人的参考是有效的,所以我将把它标记为答案。也许最好使用if(allocated.HasValue)
@asd:这完全等同于if(allocated!=null)
@Ahmad:虽然这样做可能是可行的,但我怀疑让它工作并让它继续工作比它的价值更大。如果这也生成了更可读的SQL,我也不会感到惊讶。