【问题标题】:Ignoring accents while searching the database using Entity Framework使用实体框架搜索数据​​库时忽略重音符号
【发布时间】:2011-09-15 11:41:38
【问题描述】:

我有一个数据库表,其中包含带有重音字符的名称。比如ä等等。

我需要使用 EF4 从包含一些子字符串的表中获取所有记录无论重音如何

所以下面的代码:

myEntities.Items.Where(i => i.Name.Contains("a")); 

应该返回名称中包含a 的所有项目,以及包含äâ 等的所有项目。这可能吗?

【问题讨论】:

  • 您使用的是什么数据库?您可能必须在该列上设置不区分重音的排序顺序..
  • 你可以在EF中使用这个方法吗? stackoverflow.com/questions/2461522/…
  • @Stuart Dunkeld - 成功了。我更改了数据库中 Name 列的排序规则,然后它就像一个魅力。如果您将其发布为答案,我会投票并接受它。

标签: c# entity-framework non-ascii-characters


【解决方案1】:

如果您在“名称”列上设置了不区分重音的排序规则,则查询应按要求工作。

【讨论】:

  • 如何通过代码更改特定列的排序规则?
  • @AlejandrodelRío 以blog.sqlauthority.com/2008/12/20/… 为例
  • 如果您已经创建了表并且其中包含数据,则无法执行此操作。至少在 sql server 2008 R2 中。当您创建新表或新数据库时,完全没有问题。无论如何,我的问题是关于实体框架。谢谢。
  • can change 列排序规则,只要它未被 FK、索引、检查、计算列或分布统计信息引用。 SQL 的一个示例是alter table [dbo].[Table] ALTER COLUMN [ColumnName] nvarchar(MAX) COLLATE SQL_Latin1_General_CP1_CI_AI;
  • 排序规则不会在插入时删除重音符号吗?
【解决方案2】:

设置不区分重音的排序规则将解决问题。

您可以使用下一个查询更改 SQL Server 和 Azure 数据库中列的排序规则。

ALTER TABLE TableName
ALTER COLUMN ColumnName NVARCHAR (100)
COLLATE SQL_LATIN1_GENERAL_CP1_CI_AI NOT NULL

SQL_LATIN1_GENERAL_CP1_CI_AI 是排序规则,其中LATIN1_GENERAL 是英语(美国),CP1 是代码页 1252,CI 不区分大小写,AI 不区分重音。

【讨论】:

    【解决方案3】:

    我知道这不是那么干净的解决方案,但是在阅读了this 之后,我尝试了这样的事情:

    var query = this.DataContext.Users.SqlQuery(string.Format("SELECT *  FROM dbo.Users WHERE LastName like '%{0}%' COLLATE Latin1_general_CI_AI", parameters.SearchTerm));
    

    之后,您仍然可以调用“查询”对象上的方法,例如 Count、OrderBy、Skip 等。

    【讨论】:

      【解决方案4】:

      您可以创建一个 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
      

      然后通过将其映射到属性 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)
              {
              }
      }
      

      并在 LINQ 查询中使用它,例如:

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

      【讨论】:

        【解决方案5】:

        Stuart Dunkeld 建议的不区分重音的排序规则绝对是最好的解决方案...

        但也许很高兴知道:

        Michael Kaplan 曾经发布过关于剥离变音符号的帖子:

        static string RemoveDiacritics(string stIn)
        {
            string stFormD = stIn.Normalize(NormalizationForm.FormD);
            StringBuilder sb = new StringBuilder();
        
            for(int ich = 0; ich < stFormD.Length; ich++)
            {
                UnicodeCategory uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]);
                if(uc != UnicodeCategory.NonSpacingMark)
                {
                    sb.Append(stFormD[ich]);
                }
            }
        
            return(sb.ToString().Normalize(NormalizationForm.FormC));
        }
        

        Source

        所以你的代码是:

        myEntities.Items.Where(i => RemoveDiacritics(i.Name).Contains("a")); 
        

        【讨论】:

        • 您的示例将无法运行,因为RemoveDiacritics 必须在 SQL 服务器上运行。
        • 正如@Ladislav 所说,这将从 input 字符串中去除重音(可能已经没有重音)并检查仍然考虑重音的数据库。这实际上会使情况变得更糟,因为输入的 â 将被转换为 a,即使用户在执行搜索时确实费心写重音,甚至在数据库中也找不到 â。但是.. 很高兴知道如果我需要这样做,有一种方法可以在 C# 中去除字符串的重音;)
        • @Øyvind Knobloch-Bråthen - 我认为您的输入字符串将是 "a"i.Name 数据库中的字符串,但是如果有更多麻烦,这只是一种剥离这些字符串的方法带口音等=D
        猜你喜欢
        • 2023-03-24
        • 1970-01-01
        • 2014-07-03
        • 2011-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多