我有一个方法查询,如下所示:
public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
using (var db = new L2SDataContext())
{
var result = from bo in db.BusinessObjects
where (filterId.HasValue)
? bo.Filter == filterId.value
: true
orderby bo.Name
select SqlModelConverters.ConvertBusinessObject(bo);
return result.ToList();
}
}在运行时,这将抛出一个System.InvalidOperationException: Nullable object must have a value.
看看调试器,问题出在我的Where子句: filterId.value To SQL尝试将整个东西转换成SQL,所以即使Linq为NULL,它仍然会尝试访问Linq。
我认为/希望C#编译器/CLR会将where子句作为代码块进行计算,并且只将两个分支中的一个分支发送到Linq to SQL,但这不是它的工作方式。
我的重构版本可以工作,但不是很优雅:
public IList<BusinessObject> GetBusinessObject(Guid? filterId)
{
using (var db = new L2SDataContext())
{
var temp = from bo in db.BusinessObjects select bo;
if(filterId.HasValue) temp = temp.Where(t => t.Filter == filterId.Value);
var result = from t in temp
orderby t.Name
select SqlModelConverters.ConvertBusinessObject(bo);
return result.ToList();
}
}我知道Lazy-Evaluation将确保只发送一个查询,但是有temp对象并不是很好。
发布于 2010-12-16 04:24:37
你有没有尝试:
where filterId == null || t.Filter == filterId发布于 2010-12-16 04:24:12
你的修复是完全正确的。您实际上是在尝试根据您的函数输入动态构建一个查询。省略where子句而不是提供WHERE TRUE是一个好主意。如果我要写这个查询,我会自己使用你的修复版本。
它不像使用language关键字那样漂亮,但在我看来,它仍然是处理查询的正确方法。
https://stackoverflow.com/questions/4454493
复制相似问题