LINQ不能使用string.contains?

mar*_*zzz 14 .net c# linq linq-to-entities linq-to-sql

这是我的代码:

string queryString = "Marco".ToLower();
utenti = db.User.Where(p => 
        queryString.Contains(p.Nickname.ToLower()) ||
            queryString.Contains(p.Nome.ToLower()) ||
            queryString.Contains(p.Cognome.ToLower())).ToList();
Run Code Online (Sandbox Code Playgroud)

但我得到:

String.Contains方法仅支持可在客户端上计算的参数.

为什么?我不能用.Contains()吗?

dan*_*wig 30

试试.IndexOf.它不是LINQ不能做的Contains,它的LINQ to Entities和LINQ to SQL不能.

string queryString = "Marco";
utenti = db.User.Where(p => 
    queryString.IndexOf(p.Nickname, StringComparison.OrdinalIgnoreCase) >= 0 ||
        queryString.IndexOf(p.Nome, StringComparison.OrdinalIgnoreCase) >= 0 ||
        queryString.IndexOf(p.Cognom, StringComparison.OrdinalIgnoreCasee) >= 0)
.ToList();
Run Code Online (Sandbox Code Playgroud)

为什么?

LINQ使用延迟执行.这意味着它等待您想要在执行任何操作之前迭代查询结果.LINQ有3种主要类型:

  1. LINQ to Objects - 当你IEnumerable已经在堆上时.
  2. LINQ to Entities - 当您想使用Entity Framework查询数据库时.
  3. LINQ to SQL - 当您想使用LINQ to SQL查询数据库时.

在第二2的上下文中延迟执行意味着直到枚举在结果查询未在数据库上执行的foreach块,或调用一个枚举方法等.ToList,.ToArray等之前,查询只是存储在表达式树记忆.

如果db.User是内存中的集合,您的查询将只用于peachy .但是,当数据在数据库中时,LINQ to Entities(或LINQ to SQL)必须将表达式树转换为它所谓的"存储表达式" - 这对于"将我的LINQ表达式转换为SQL"来说只是花哨的讨论.

现在假设您有一个想要用于查询的自定义C#算法,并且您做了类似这样的事情:

var result = db.User.Where(x => MyCustomMethod(x));
Run Code Online (Sandbox Code Playgroud)

今天LINQ to Entities无法将您的C#代码转换为SQL查询(存储表达式).每天依赖的许多其他C#方法也是如此.它也并不支持.ToLower,.ToUpper,.StartsWith,.EndsWith,等有C#的方法,可以转换为存储表达式,数量有限,.IndexOf恰好是其中之一.

但是请记住,Contains我们在这里讨论的只是字符串对象的方法,这对于商店表达式是不支持的.LINQ到实体不支持.ContainsIEnumerable秒.以下是有效的,将与LINQ to Entities一起使用(不确定LINQ to SQL):

var idsIWantToFind = new[] { 1, 2, 3 };
var users = db.Where(x => idsIWantToFind.Contains(x.UserId));
Run Code Online (Sandbox Code Playgroud)

以上相当于做一个SQL WHERE UserId IN (1, 2, 3)谓词.

  • 为了扩展这一点,并帮助澄清问题,`Where`中的代码需要转换为真正的SQL.并非每个功能都能做到这一点.因此,你有一些可以转换的东西(例如`IndexOf`),然后你还有实体数据库扩展,可以做一些像日期比较等的东西. (3认同)
  • 要扩展@ neoistheone的评论,请考虑尝试做一些类似`.Where(x => MyCustomMethod(x))`的内容.数据库不知道如何在SQL中调用该自定义方法.它与其他方法相同,如`.StartsWith`,`.Contains`等.当某些方法可以转换为商店表达式(SQL)时,支持某些方法,其余方法则不支持. (2认同)