LINQ to Entities无法识别方法IsNullOrWhiteSpace

9
我有以下代码:

我有以下代码:

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;

这段代码使用Entity Framework v6 Code First与SQL数据库交互。

除了性能方面的考虑,如果我不包含IsNullOrWhitespace,当过滤条件为空时(我测试过null和空值),我将得不到任何结果;然而当有值存在时,它可以按预期工作。

我遇到了以下错误:

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)。我在这里看到了很多成功实现的帖子,所以想知道是否有基本的东西我没有注意到?


1
这是因为该语句被翻译为在数据库上执行的SQL语句,而SQL不理解IsNullOrWhiteSpace - Matas Vaitkevicius
4个回答

19
如果您希望在当前形式下使用您的声明,您可能需要进行替换。
string.IsNullOrWhiteSpace(searchAlpha2)
!(searchAlpha2 == null || searchAlpha2.Trim() == string.Empty)

还有其他所有的值,才能将其翻译为可用的SQL。

更新:从@DavidKempfner的评论中复制

EntityFramework.6.2.0 版本开始,它生成的 SQL 会检查:
!(searchAlpha2.Trim() == string.Empty),
也就是说,它忽略了 searchAlpha2 == null || 部分。

请改用以下方法:

!string.IsNullOrEmpty(entity.searchAlpha2.Trim())

1
我正在使用EntityFramework.6.2.0,但这对我没有起作用。它生成了一个SQL查询,检查 !(searchAlpha2.Trim() == string.Empty),忽略了 searchAlpha2 == null || 的部分。 我不得不改为使用以下代码: !string.IsNullOrEmpty(entity.searchAlpha2.Trim()) - David Klempfner

7
我建议采用不同的方法——利用动态建立查询的能力,从而避免完全传递可选查询参数到表达式中——这将导致分析为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);

2
很好的提示;我以前没有接触过PredicateBuilder;谢谢。 - JohnLBevan

1
当您在Entity Framework中使用LINQ从数据库获取数据时,您需要仅使用实体框架可以转换为SQL查询的函数。

0

我知道这个问题已经有一个被接受的答案,但我有一个想法要分享。

不要在LINQ中放置多个检查或使用if语句来应用where子句列表结果,您可以使用一个简单的技巧。只需声明一个bool变量并将IsNullOrWhitespace添加到linq中即可:

bool isNull = string.IsNullOrWhiteSpace(searchAlpha2); 
var countries = db.Countries.Where(c => isNull  || c.Alpha2.Contains(searchAlpha2)).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接