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.SqlServerLinq 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。真的吗?

LINQ To Entities 无法识别方法 Last。真的吗?

C# LINQ to Entities 无法识别方法“布尔”