LINQ包含不区分大小写的


173

该代码区分大小写,如何使其不区分大小写?

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM.Where(fi => fi.DESCRIPTION.Contains(description));
}

Sjoerd的答案是正确的,但是...写i时,我想获得带有土耳其İ(例如)的名字的搜索结果,反之亦然。在这种情况下,ToLower似乎是正确的方法。如果我错了,请纠正我。关于土耳其语©:en.wikipedia.org/wiki/Dotted_and_dotless_I
He Nrik

@HeNrik-正如JYelton评论中的“土耳其测试”链接中所讨论的那样,在接受土耳其文化的情况下,这两个i是不同的-因此您将找不到其他i的名字。您想要ToLowerInvariant。在这里查看有关各种答案的讨论。
ToolmakerSteve

这是一个古老的问题,但是值得注意的是,在当前版本中,EF核心2.0 ToLower()的工作方式如下person.Where(p => p.Name.ToLower()。Contains(myParam.Name.ToLower() )); 我在针对Postgres DB的Linq查询中使用它。我对数据库中的列排序规则没有大小写不敏感,并且我检查了没有ToLower()的情况下匹配是否明显区分大小写。
shelbypereira

Answers:


72

假设我们在这里使用字符串,这是另一个使用的“优雅”解决方案IndexOf()

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
        .Where(fi => fi.DESCRIPTION
                       .IndexOf(description, StringComparison.OrdinalIgnoreCase) != -1);
}

7
真好 但是出于我自己的目的,这对于LINQ to Entities无效。LINQ to Objects的不错解决方案。
Damian Powell

242
fi => fi.DESCRIPTION.ToLower().Contains(description.ToLower())

49
正如乔恩•斯基特Jon Skeet)在一个相关问题上所说的那样,这种方法不能通过土耳其试验
JYelton 2012年

5
否,但是数据库无法使用字符集和排序规则。如果您试图将工作推向数据库,则必须对字符集和排序规则做出一些假设,对吗?
Christopher Stevenson

66
包含应该使用using IEqualityComparer<string>属性来处理比较的工作方式。使用ToLower和ToUpper检查相等性是一个坏主意。试试:.Contains(description, StringComparer.CurrentCultureIgnoreCase)例如
Dorival

19
@Dorival的评论不起作用,因为它给出了此错误消息:Error 1 'string' does not contain a definition for 'Contains' and the best extension method overload 'System.Linq.ParallelEnumerable.Contains<TSource>(System.Linq.ParallelQuery<TSource>, TSource, System.Collections.Generic.IEqualityComparer<TSource>)' has some invalid arguments
eMi 2015年

6
ContainsStringComparer不会接收字符串作为参数,因此会出现构建错误。IndexOfQueryable可能不能转换成SQL。我个人认为当我们谈到数据库的LINQ时,这个答案是完全有效的。
Thariq Nugrohotomo 2015年

121

如果LINQ查询是在数据库上下文中执行的,则对的调用将Contains()映射到LIKE运算符:

.Where(a => a.Field.Contains("hello")) 成为Field LIKE '%hello%'LIKE默认情况下,该运算符不区分大小写,但是可以通过更改column的排序规则来更改。

如果LINQ查询是在.NET上下文中执行的,则可以使用IndexOf(),但是LINQ to SQL不支持该方法。

LINQ to SQL 不支持将CultureInfo作为参数的方法,这可能是因为它不能保证SQL Server处理与.NET相同的区域性。这并非完全正确,因为它确实支持StartsWith(string, StringComparison)

但是,它似乎不支持LIKE在LINQ to SQL中求值的方法以及在.NET中不区分大小写的比较的方法,从而不可能以一致的方式执行不区分大小写的Contains()。


仅FYI EF 4.3不支持StartsWith。我得到:LINQ to Entities无法识别方法'Boolean StartsWith(System.String,System.StringComparison)'
nakhli 2013年

StartWith转换为LIKE'hello%'吗?
Bart Calixto 2014年

clicdata链接已死。
亚当·帕金

2
深入研究LIKE子句的生成的SQL和数据库行为的努力
Thariq Nugrohotomo 2015年

1
因此,使用EF时有哪些选择?在一种情况下,我需要进行大小写insensitive搜索,在另一种情况下,我需要进行大小写搜索case sensitive。我是否只需要敲击性能并使用'toLower()'?
Zapnologica

12

此处接受的答案没有提及以下事实:如果您具有空字符串,则ToLower()会引发异常。比较安全的方法是:

fi => (fi.DESCRIPTION ?? string.Empty).ToLower().Contains((description ?? string.Empty).ToLower())

您无法在翻译为SQL的查询上生成异常
Alex Zhukovskiy

@AlexZhukovskiy这与这个问题有什么关系?如果fi.DESCRIPTION为null或description为null,则将获得C#null引用异常。LINQ查询在SQL端转换为什么都没有关系。证明如下:dotnetfiddle.net/5pZ1dY
Marko,

由于此查询不支持空合并运算符,因此无法转换为SQL。您可能查询数据库,而不是加载所有条目以在客户端使用空合并。因此,如果您使用它-可以在客户端使用,但在DB上失败,否则您可以在DB上使用,并且不必在客户端使用nullref,因为不会发生,因为C#不会执行此查询并且不会实际上没有读取空对象。
亚历克斯·朱可夫斯基

这个答案帮助我解决了在LINQ to Entities上遇到的一个问题,我正在执行.IndexOf和.Contains包含一个IEnumerable,其中来自数据库的字符串值为空。在枚举结果之前,我没有收到错误,然后收到错误消息“对象引用未设置为对象的实例”。在看到这篇文章之前,我不知道为什么会这样。谢谢!
randyh22 '18

7

对于LINQ to Objects,使用C#6.0(允许表达式表示函数和null传播),可以像这样在单行中完成(也检查null):

public static bool ContainsInsensitive(this string str, string value) => str?.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0;

它不起作用,因为ContainsInsensitive不是存储命令
Sven

@Sven-是的,它仅适用于LINQ to Objects。我已确定答案。谢谢。
Alexei

4

IndexOf在这种情况下效果最好

return this
   .ObjectContext
   .FACILITY_ITEM
   .Where(fi => fi.DESCRIPTION.IndexOf(description, StringComparison.OrdinalIgnoreCase)>=0);

3

您可以使用string.Compare

    lst.Where(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0);

如果您只想检查包含,则使用“任何”

  lst.Any(x => string.Compare(x,"valueToCompare",StringComparison.InvariantCultureIgnoreCase)==0)

这不能回答问题。OP正在询问字符串中的 “包含” (即,一个字符串包含另一个字符串),而不是字符串集合是否包含单个字符串。
andrewf

1
public static bool Contains(this string input, string findMe, StringComparison comparisonType)
{
    return String.IsNullOrWhiteSpace(input) ? false : input.IndexOf(findMe, comparisonType) > -1;
}

2
我们可以在linq查询中使用自定义扩展方法吗?你确定吗 ?
维沙尔·沙尔玛(Vishal Sharma)2013年


0

老实说,这并不需要困难。似乎一开始就是这样,但事实并非如此。这是一个完全按照要求执行的C#中的简单linq查询。

在我的示例中,我正在处理具有一个名为FirstName的属性的人员列表。

var results = ClientsRepository().Where(c => c.FirstName.ToLower().Contains(searchText.ToLower())).ToList();

这将在小写搜索中搜索数据库,但返回全写结果。


-2

使用String.Equals方法

public IQueryable<FACILITY_ITEM> GetFacilityItemRootByDescription(string description)
{
    return this.ObjectContext.FACILITY_ITEM
           .Where(fi => fi.DESCRIPTION
           .Equals(description, StringComparison.OrdinalIgnoreCase));
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.