LINQ to Entities 无法识别方法 IsNullOrWhiteSpace
Posted
技术标签:
【中文标题】LINQ to Entities 无法识别方法 IsNullOrWhiteSpace【英文标题】:LINQ to Entities does not recognize the method IsNullOrWhiteSpace 【发布时间】:2014-08-09 00:08:48 【问题描述】:我有以下代码:
var countries = from c in db.Countries
where (string.IsNullOrWhiteSpace(searchAlpha2) || (c.Alpha2 ?? string.Empty).ToUpper().Contains(searchAlpha2.ToUpper()))
&& (string.IsNullOrWhiteSpace(searchAlpha2) || (c.Alpha3 ?? string.Empty).ToUpper().Contains(searchAlpha3.ToUpper()))
&& (string.IsNullOrWhiteSpace(searchName) || (c.Name ?? string.Empty).ToUpper().Contains(searchName.ToUpper()))
select c;
此代码在 SQL 数据库上使用 Entity Framework v6 Code First。
除了性能之外,如果我不包含IsNullOrWhitespace
,那么当过滤条件为空时(我已经测试了空值和空值),我不会得到任何结果;但是,当存在值时,这将按预期工作。
我收到了错误:
LINQ to Entities does not recognize the method 'Boolean IsNullOrWhiteSpace(System.String)' method, and this method cannot be translated into a store expression.
我正在尝试使用 searchXXX 字符串来过滤列。我试过使用 RegEx.IsMatch、SqlMethods.Like 和下面的代码,但都给我错误,说这些函数是不允许的(错误来自 EntityFramework.SqlServer
或 Linq to Entities
)。不过,我在这里看到很多帖子都成功地做到了这一点 - 所以想知道我是否遗漏了一些基本的东西?
【问题讨论】:
这是因为该语句被翻译成在 DB 上执行的 SQL 并且 SQL 不理解IsNullOrWhiteSpace
【参考方案1】:
如果您想以当前形式使用您的语句,您可能需要替换
string.IsNullOrWhiteSpace(searchAlpha2)
到
!(searchAlpha2 == null || searchAlpha2.Trim() == string.Empty)
以及所有其他值,以便将其转换为工作 SQL。
【讨论】:
【参考方案2】:我会建议一种不同的方法 - 使用动态构建查询的能力,从而避免将可选的查询参数完全传递给表达式 - 这将导致在解析为 sql 并在数据库上执行时改进查询计划。
另外,如果您的数据库 (?SqlServer) 未设置为区分大小写的排序规则(即xx_CI_xx
),您也可以避免大小写转换,因为它是多余的:
var myQueryable = db.Countries.AsQueryable();
if (!string.IsNullOrWhiteSpace(searchAlpha2))
myQueryable = myQueryable.Where(c => c.Alpha2.Contains(searchAlpha2));
...
var countries = myQueryable.ToList();
您可以使用 PredicateBuilder 获得此功能以及更多功能
更新
JB:根据 StuartLC 的回答,这是修改为使用 PredicateBuilder 的代码:
var predicate = PredicateBuilder.True<Country>();
if (!string.IsNullOrWhiteSpace(searchAlpha2))
predicate = predicate.And(c => c.Alpha2 != null ? c.Alpha2.Contains(searchAlpha2) : false);
if (!string.IsNullOrWhiteSpace(searchAlpha3))
predicate = predicate.And(c => c.Alpha3 != null ? c.Alpha3.Contains(searchAlpha3) : false);
if (!string.IsNullOrWhiteSpace(searchName))
predicate = predicate.And(c => c.Name != null ? c.Name.Contains(searchName) : false);
IQueryable<Country> countries = db.Countries.AsExpandable().Where(predicate);
【讨论】:
很棒的提示;我以前没有遇到过 PredicateBuilder。谢谢。【参考方案3】:当您在实体框架中使用 linq 从数据库中获取数据时,您只需要使用实体框架可以转换为 sql 查询的函数。
【讨论】:
【参考方案4】:我知道这个问题的答案已经被接受,但我有一个想法要分享。
您可以使用一个简单的技巧,而不是在 LINQ 中进行多项检查或使用 if 语句将 where 子句应用于列表结果。只需声明一个布尔变量并将添加的 IsNullOrWhitespace 分配给 linq,如:
bool isNull = string.IsNullOrWhiteSpace(searchAlpha2);
var countries = db.Countries.Where(c => isNull || c.Alpha2.Contains(searchAlpha2)).ToList();
【讨论】:
以上是关于LINQ to Entities 无法识别方法 IsNullOrWhiteSpace的主要内容,如果未能解决你的问题,请参考以下文章
LINQ to Entities 无法识别方法“布尔包含 [Int32]
LINQ to Entities 无法识别方法 IsNullOrWhiteSpace
错误:LINQ to Entities 无法识别方法 DataLength
LINQ To Entities 无法识别方法 Last。真的吗?