在linq查询中处理可空布尔

时间:2019-05-23 09:05:35

标签: c# linq

我遇到一种情况,我将可为空的布尔值传递给该方法,然后在linq查询中,如果该参数为null,则需要获取所有记录,否则进行比较并返回相对值。

这是我尝试过的方法(简化了只询问相关问题的方法)

public List<Something> Fetch(bool? allocated = null){
   return (from x in DbContext.Something 
            where x.Active && (allocated == null || x.Allocated == allocated.Value)
            select x).ToList();
}

我也检查了allocated.HasValue,但是每次都出现相同的问题。

我得到的异常是:

  

System.InvalidOperationException:“可为空的对象必须具有一个值。”

3 个答案:

答案 0 :(得分:6)

我现在还不清楚为什么失败了,但是当我遇到这样的问题时,我倾向于尝试简化查询。特别是,“将表达式树转换为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();
}

答案 1 :(得分:1)

投票给 Jon Skeet 答复。

但是有一些解释为什么会发生这种情况, Linq处理空值没有问题。

但是LINQ to SQL或Linq to实体(EF)投影的行为会有所不同!不确定是错误还是功能,但无法转换为T-SQL。 Google搜索: linq到实体或linq到sql比较可为空的类型以获取答案。

为了避免无法转换为T-SQL的NULL = 1比较,我通常这样做

var allocated = (bool?)null;

这对您的方法的可选参数无效,默认为“ 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();
}

答案 2 :(得分:0)

代替像 John skeet 中所述的单独的where子句,只需执行

 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();
}

我已经检查过了。它工作正常。