忽略重音和大小写

本文关键字:大小写 | 更新日期: 2023-09-27 18:08:39

通过忽略重音和大小写的Where方法使用LINQ过滤元素的最简单方法是什么?

到目前为止,我已经能够通过调用属性上的方法来忽略大小写,我认为这不是一个好主意,因为它为每个元素调用相同的方法(对吗?)

这是我目前得到的:

var result = from p in People
             where p.Name.ToUpper().Contains(filter.ToUpper())
             select p;

请告诉我这是不是一个好的做法,也是忽略重音的最简单的方法。

忽略重音和大小写

要忽略大小写和重音(变音符),您可以首先定义一个扩展方法,如下所示:

    public static string RemoveDiacritics(this String s)
    {
        String normalizedString = s.Normalize(NormalizationForm.FormD);
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < normalizedString.Length; i++)
        {
            Char c = normalizedString[i];
            if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
                stringBuilder.Append(c);
        }
        return stringBuilder.ToString();
    }

(从在字符串比较中忽略重音字母修改)

现在你可以运行你的查询:

string queryText = filter.ToUpper().RemoveDiacritics();
var result = from p in People
         where p.Name.ToUpper().RemoveDiacritics() == queryText
         select p;

如果你只是在c#中迭代一个集合,这是很好的,但如果你使用LINQ to SQL,最好避免在你的LINQ查询中使用非标准方法(包括扩展方法)。这是因为你的代码不能转换成有效的SQL,因此运行在SQL Server与所有可爱的性能优化。

由于在LINQ to SQL中似乎没有忽略重音的标准方法,在这种情况下,我建议将您想要搜索的字段类型更改为大小写和重音不敏感(CI_AI)。

用你的例子:

ALTER TABLE People ALTER COLUMN Name [varchar](100) COLLATE SQL_Latin1_General_CP1_CI_AI

你的查询现在应该忽略重音和大小写。

请注意,在运行上述查询之前,您需要暂时删除字段上的任何唯一约束,例如
ALTER TABLE People DROP CONSTRAINT UQ_People_Name

现在您的LINQ查询将简单地为:

var result = from p in People
         where p.Name == filter
         select p;

对于口音,如果您无法更新数据库模式或在RAM中获取整个列表,则可以枚举所有口音(此处为法语):

var result = from p in People
             where p.Name.ToLower()
                .Replace("à", "a")
                .Replace("â", "a")
                .Replace("ä", "a")
                .Replace("ç", "c")
                .Replace("é", "e")
                .Replace("è", "e")
                .Replace("ê", "e")
                .Replace("ë", "e")
                .Replace("î", "i")
                .Replace("ï", "i")
                .Replace("ô", "o")
                .Replace("ù", "u")
                .Replace("û", "u")
                .Replace("ü", "u").Contains(RemoveDiacritics(filter.ToLower()))
             select p;
                

更改排序规则:

ALTER TABLE dbo.MyTable 
ALTER COLUMN CharCol varchar(10)**COLLATE Latin1_General_CI_AS** NOT NULL;

下面是一些允许忽略重音的比较的代码:

忽略字符串比较中的重音字母

我将有礼貌的不复制代码,使作者可以得到代表他的回答。现在,回答你的问题:

你会得到这段代码并像这样使用它:

var result = from p in People
             where p.Name.ToUpper().Contains(RemoveDiacritics(filter.ToUpper()))
             select p;

您甚至可以将该代码转换为扩展方法。我有:)

遵循Dunc更改整个数据库排序的解决方案,这里是一个完整的教程,涉及索引,键等:

https://www.codeproject.com/Articles/302405/The-Easy-way-of-changing-Collation-of-all-Database

(一定要先看完所有的评论)

如果你使用链接到实体,你可以:

1。创建一个SQL函数,通过对输入字符串应用排序规则SQL_Latin1_General_CP1253_CI_AI来删除变音符号,例如:

CREATE FUNCTION [dbo].[RemoveDiacritics] (
@input varchar(max)
)   RETURNS varchar(max)
AS BEGIN
DECLARE @result VARCHAR(max);
select @result = @input collate SQL_Latin1_General_CP1253_CI_AI
return @result
END

2。通过将其映射为属性DbFunction,将其添加到DB上下文中(在本例中为ApplicationDbContext),例如:

 public class ApplicationDbContext : IdentityDbContext<CustomIdentityUser>
    {
        [DbFunction("RemoveDiacritics", "dbo")]
        public static string RemoveDiacritics(string input)
        {
            throw new NotImplementedException("This method can only be used with LINQ.");
        }
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options)
        {
        }
}

3。在LINQ查询中使用,例如:

var query = await db.Users.Where(a => ApplicationDbContext.RemoveDiacritics(a.Name).Contains(ApplicationDbContext.RemoveDiacritics(filter))).tolListAsync();

过滤器您想要搜索的字符串,在本例中为表Users of the DB的列名。

从Entity Framework Core 5.0开始,您现在可以在Linq到SQL的运行中更改查询的排序。

因此,对于您的示例,如果我想忽略大小写和重音,我会这样做:

(注意不能使用contains,但可以使用SQL的like操作符)

var result = from p in People
             where EF.Functions.Like(EF.Functions.Collate(p.Name, "Latin1_General_CI_AI"), $"%{filter}%")
             select p;

Latin1_General_CI_AI是大小写不敏感(CI)和重音不敏感(AI)

更多关于EF排序和EF区分大小写的信息:

https://learn.microsoft.com/en-us/ef/core/miscellaneous/collations-and-case-sensitivity explicit-collation-in-a-query