我有以下代码:
return this.ObjectContext.BranchCostDetails.Where(
b => b.TarrifId == tariffId && b.Diameter == diameter
|| (b.TarrifId==tariffId && !string.IsNullOrWhiteSpace(b.Diameter))
|| (!b.TarrifId.HasValue) && b.Diameter==diameter);
当我尝试运行代码时出现此错误:
LINQ to Entities无法识别方法'Boolean IsNullOrWhiteSpace(System.String)'方法,并且此方法无法转换为商店表达式 . “
我怎样才能解决这个问题并编写比这更好的代码?
4 回答
你需要更换
同
对于Linq to Entities,这被转换为:
而对于Linq到SQL差不多但不完全相同
在这种情况下,区分
IQueryable<T>
和IEnumerable<T>
很重要 . 简而言之,IQueryable<T>
由LINQ提供程序处理以提供优化的查询 . 在此转换期间,并非所有C#语句都受支持,因为它们无法将它们转换为后端特定查询(例如SQL),或者因为实现者没有预见到需要该语句 .相反,
IEnumerable<T>
针对具体对象执行,因此不会被转换 . 因此,很常见的是,IEnumerable<T>
可以使用的构造不能与IQueryable<T>
一起使用,并且由不同LINQ提供程序支持的IQueryables<T>
不支持同一组函数 .但是,有一些解决方法(如Phil's answer)可以修改查询 . 此外,作为一种更通用的方法,可以在继续查询规范之前回退到
IEnumerable<T>
. 但是,这可能会影响性能 - 特别是在限制时使用它(例如where子句) . 相比之下,在处理转换时,性能损失要小得多,有时甚至不存在 - 取决于您的查询 .所以上面的代码也可以像这样重写:
NOTE: 该代码将比Phil's answer具有更高的性能影响 . 但是,它显示了原理 .
使用表达式visitor来检测对string.IsNullOrWhiteSpace的引用,并将它们分解为更简单的表达式
(x == null || x.Trim() == string.Empty)
.以下是扩展访问者和使用它的扩展方法 . 它不需要使用特殊配置,只需调用WhereEx而不是Where .
因此,如果您运行
myqueryable.WhereEx(c=> !c.Name.IsNullOrWhiteSpace())
,它将被转换为!(c.Name == null || x.Trim() == "")
,然后传递给任何(linq到sql / entities)并转换为sql .您也可以使用它来检查空格: