【问题标题】:LINQ can't use string.contains?LINQ 不能使用 string.contains?
【发布时间】:2013-11-16 11:11:33
【问题描述】:

这是我的代码:

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();

但我明白了:

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

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

【问题讨论】:

    标签: c# .net linq linq-to-sql linq-to-entities


    【解决方案1】:

    问题是输入的优先级。 例如:

    a.包含(b);或 b.Contains(a);

    你最好写:

    p.Nickname.Contains(queryString) ...
    

    而不是

    queryString.Contains(p.Nickname) ...
    

    【讨论】:

      【解决方案2】:

      试试.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();
      

      为什么?

      LINQ 使用deferred execution。这意味着它会等到您想要遍历查询结果时才会执行任何操作。 LINQ 主要有 3 种类型:

      1. LINQ to Objects - 当您的 IEnumerable 已经在堆上时。
      2. LINQ to Entities - 当您想使用实体框架查询数据库时。
      3. LINQ to SQL - 当您想使用 LINQ to SQL 查询数据库时。

      第二个 2 的上下文中的延迟执行意味着您的查询不会在数据库上执行,直到您在 foreach 块中枚举结果,或调用像 .ToList.ToArray 等枚举方法。在此之前,您的查询只是作为表达式树存储在内存中。

      如果db.User 是内存中的一个集合,那么您的查询将非常有效。但是,当数据在数据库中时,LINQ to Entities(或 LINQ to SQL)必须将您的表达式树转换为它所谓的“存储表达式”——这只是“将我的 LINQ 表达式转换为 SQL”的花哨的说法。

      现在假设您有一个想要用于查询的自定义 C# 算法,并且您执行了如下操作:

      var result = db.User.Where(x => MyCustomMethod(x));
      

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

      但是请记住,只有我们在这里讨论的字符串对象的Contains 方法不支持存储表达式。 LINQ to Entities 确实支持IEnumerables 上的.Contains。以下是有效的,并且可以与 LINQ to Entities 一起使用(不确定 LINQ to SQL):

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

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

      【讨论】:

      • 为了对此进行扩展,并帮助澄清问题,Where 中的代码需要转换为真正的 SQL。不是每个函数都能做到这一点。因此,你有一部分可以转换的东西(例如IndexOf),然后你还有实体数据库扩展,可以做一些事情,比如日期比较等。
      • 要扩展@neoistheone 的评论,请考虑尝试执行.Where(x => MyCustomMethod(x)) 之类的操作。数据库不知道如何在 SQL 中调用该自定义方法。与.StartsWith.Contains等其他方法相同。有些方法可以转换为存储表达式(SQL)时支持,其余的则不支持。
      • 我想我们现在已经掌握了一切。 :D
      • 我建议你添加这两个 cmets 来回答,因为它们比现在回答的更有价值(这让人们明白为什么它不起作用):)
      • linq to entities 中使用ToLowerToUpperStartsWithEndsWithContains(在字符串上)时,我从未遇到任何错误...解释仅对linq to sql 有效(我没有经验),否则这是另一个问题。
      猜你喜欢
      • 2021-05-03
      • 2019-01-08
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 2011-11-02
      • 2010-12-10
      • 2012-01-15
      • 2021-10-11
      相关资源
      最近更新 更多