LINQ表达式未转换为SQL

时间:2017-10-26 10:43:16

标签: c# entity-framework linq .net-core entity-framework-core

我正在尝试从LINQ实现编译的SQL查询,该查询将检查query是否是数据库中三列中的任何一列的子串(不区分大小写)。

我正在使用.NET Core 1.1

我提出的查询如下:

users.Select(u => new
  {
    User = u,
    query = u.FirstName.ToLower() + u.LastName.ToLower() + u.Email.ToLower()
  }).Where(x => x.query.Contains(query))

但是在查看调试信息时,我收到了这个警告:

  

LINQ表达式'(([u] .FirstName.ToLower()+ [u] .LastName.ToLower())+ [u] .Email.ToLower())。包含(__ query_0)'无法翻译并将在当地进行评估。

我尝试过的第二个查询:

 users.Where(x => u.FirstName.ToLower().Contains(query) || u.LastName.ToLower().Contains(query) || u.Email.ToLower().Contains(query))

但它给了我完全相同的警告。

为什么会这样? 我正在寻找类似的东西:

SELECT * FROM USERS WHERE FirstName LIKE query OR LastName LIKE query OR Email LIKE query

更新

我再做了一次实验:

    users.Where(u =>
    u.FirstName.Contains(query) ||
    u.LastName.Contains(query) ||
    u.Email.Contains(query));

这也导致了

  

LINQ表达式'(([u] .FirstName.Contains(__ query_0)OrElse [u] .LastName.Contains(__ query_1))OrElse   [u] .Email.Contains(__ query_2))'无法翻译,将会   在当地评估。

1 个答案:

答案 0 :(得分:6)

这是因为.ToLower().Contains()是字符串类中的函数,并且不能由linq提供程序转换为SQL。
所有查询(除非明确指定)都将遵循数据库排序规则,如果它是CI,则它是Case Insensitive,您不需要.ToLower()。 对于.Contains(),您需要使用实体函数Like

users.Where(u =>
    EF.Functions.Like(u.FirstName, "%" + query + "%") ||
    EF.Functions.Like(u.LastName, "%" + query + "%") ||
    EF.Functions.Like(u.Email, "%" + query + "%"));

然而,这似乎是在EF核心2.0中添加的。对于1.1我不认为有任何方法可以做到这一点。我建议直接跳过EF并编写普通的旧SQL。