我遇到一种情况,我将可为空的布尔值传递给该方法,然后在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:“可为空的对象必须具有一个值。”
答案 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();
}
我已经检查过了。它工作正常。