【问题标题】:Case Insensitive Array.Contains in Linq Query不区分大小写的数组。包含在 Linq 查询中
【发布时间】:2015-08-08 10:56:29
【问题描述】:

我正在尝试在 Linq 查询中的字符串数组上使用 Array.Contains:

var otherMatchingDevices = from d in selectedDevices
                           from c in mldb.Companies
                           where d.CompanyID == c.CompanyID && c.Deleted == 0
                           where searchTerms.Contains(d.Name.ToString(), StringComparer.CurrentCultureIgnoreCase) || searchTerms.Contains(c.CompanyName.ToString(), StringComparer.CurrentCultureIgnoreCase)
                           select d;

当查询被评估时,它会因“用于查询运算符'包含'的不支持的重载而崩溃。

我使用 StringComparer 测试了这段代码,它工作正常并打印出“fOO”:

string[] sList = { "fOO", "bar" };
string[] array = { "foo" };
List<string> stringlist = sList.ToList();
var qry = from s in stringlist
          where array.Contains(s, StringComparer.CurrentCultureIgnoreCase)
          select s;
if (qry.Count() > 0) Console.WriteLine(qry.First().ToString());

谁能告诉我如何在 Linq 查询中使用不区分大小写的 Array.Contains?我不想转换原始字符串 ToUpper() 或 ToLower(),因为它很昂贵并且会更改原始数据。

【问题讨论】:

  • 您使用的是 LINQ2SQL 还是 LINQ2Entities?如果是这样,那就是它不被支持的原因。
  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • @MichaelDunlap 使用 Linq to SQL 类。
  • ToUpper 可能没那么贵,你为什么这么认为?
  • @Magnus 每次我们调用 ToUpper() 时,它都会创建一个由 GC 创建和管理的临时字符串,这需要更多时间和更多内存。我也讨厌从数据库中的原始状态更改原始源数据,这让我很困惑。

标签: c# linq linq-to-sql case-insensitive stringcomparer


【解决方案1】:

您的第一个 sn-p 是使用 Linq to SQL 调用的,这意味着它最终会被翻译成 SQL。因此,比较是否区分大小写取决于表列的COLLATION。这就是 Linq 抛出异常的原因,因为它不能保证区分大小写。

您的第二个查询 sn-p 是使用 Linq to Objects 执行的,因此可以强制执行字符串相等,因为实际的 string 已经在内存中。

【讨论】:

  • 谢谢,这说明了为什么不能在 Linq to SQL 类上使用 Contains 方法,而且我也没有想到表的排序规则。谢谢@haim770
【解决方案2】:

我使用 StringComparer 测试了这段代码,它运行良好并且 打印出“fOO”:

LINQ to Objects 不同于 LINQ to SQL/Entities。后者需要将您的查询转换为 SQL 表达式,因此它不了解 StringComparsion 是什么。

您可以在查询中使用AsEnumerable() 将数据带入内存:

var otherMatchingDevices = (from d in selectedDevices
                            from c in mldb.Companies
                            where d.CompanyID == c.CompanyID && c.Deleted == 0)
                            .AsEnumerable()
                            .Where(searchTerms.Contains(d.Name.ToString(), 
                                               StringComparer.CurrentCultureIgnoreCase) || 
                                   searchTerms.Contains(c.CompanyName.ToString(), 
                                               StringComparer.CurrentCultureIgnoreCase))
                            .ToArray()

【讨论】:

  • 如果要在内存中进行过滤(强烈警告,因为它可能会很慢)我建议将searchTerms 放入不区分大小写的哈希集中。 HashSet&lt;string&gt;(StringComparer.OrdinalIgnoreCase)
  • 这里的代码不起作用,但答案很有用,我明白了基本的想法,我现在看到了问题。谢谢@Magnus
猜你喜欢
  • 2023-04-02
  • 1970-01-01
  • 2015-01-22
  • 2017-04-16
  • 2020-08-20
  • 2023-03-07
  • 2012-01-03
  • 2014-10-08
  • 2023-04-01
相关资源
最近更新 更多