在使用LINQ to SQL时忽略SQL Server中的音调

11

如何使用LINQ to SQL在查询SQL Server数据库时忽略重音符号(如´、`、~)?

更新:

仍然没有找到如何在LINQ中实现它(甚至不确定是否可能),但我设法通过更改数据库来解决此问题。 只需要更改我想要搜索的字段上的排序规则即可解决此问题。我所使用的排序规则是:

SQL_Latin1_General_CP1_CI_AS

CI表示“不区分大小写”,AS表示“区分重音符号”。只需将AS更改为AI即可使其成为“不区分重音符号”。

SQL语句如下:

ALTER TABLE table_name ALTER COLUMN column_name column_type COLLATE collation_type

标签的目的不是随便编造,主题是linq,所以只需使用“linq”,不要创建“sqltolinq”,因为没有人会再次使用这样一个随意的标签,所以这是浪费。 - TravisO
哦,我不只是创建了一个新标签,我使用了已经在约290个问题中使用的“linqtosql”... - Farinha
谢谢,我刚想应用正则表达式替换。那样做会很糟糕! - David Lay
如果我将数据库的排序规则更改为SQL_Latin1_General_CP1_CI_AS,那么在SELECT查询中,我会失去例如带有锐音符的c(U+0107)等字符,这是一个不好的副作用。 - Tomas Kubes
5个回答

3
在SQL查询中(Sql Server 2000+,据我回忆),您可以通过执行类似于select MyString,MyId from MyTable where MyString collate Latin1_General_CI_AI ='aaaa'的操作来实现这一点。
我不确定在LINQ中是否可能,但是对LINQ更熟悉的人可能可以进行翻译。
如果您希望排序和选择/where查询始终忽略重音符号,您可以更改表以指定与您关注的字段相同的排序规则。

以下是一个示例,可能是我从我的网络搜索之一中获取的,但我记不得URL。 SELECT * FROM nametable WHERE name = 'abbee' COLLATE Latin1_General_CI_AI -- 大小写不敏感,重音符号不敏感比较 AND <anotherColumn> LIKE '%Accent%' COLLATE Latin1_General_CI_AS -- 大小写不敏感,重音符号敏感比较 ORDER BY <yetAnotherColumn> DESC COLLATE Latin1_General_CS_AS -- 大小写敏感,重音符号敏感排序 - Raj

2
请参考以下答案:

LINQ Where Ignore Accentuation and Case

基本上,您需要修改SQL Server中的字段类型,例如:

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

似乎没有使用LINQ的方法可以做到这一点,除非调用一个自定义方法来去除变音符号(这将不是高效的)。


1

看起来在 Linq to SQL 中有一种方法可以通过使用 T-SQL 函数来忽略排序规则的差异:

CREATE FUNCTION [dbo].[func_ConcatWithoutCollation]
(
    @param1 varchar(2000),
    @param2 varchar(2000)
)
RETURNS varchar(4000)
AS
BEGIN
    IF (@param1 IS NULL) SET @param1 = ''
    IF (@param2 IS NULL) SET @param2 = ''
    RETURN @param1 COLLATE Latin1_General_CS_AS + @param2 COLLATE Latin1_General_CS_AS
END

要在Linq to SQL中使用此功能,需要使用SqlMetal工具中的一个开关:/functions。 例如:

"%ProgramFiles%\Microsoft SDKs\Windows\v7.0A\Bin\SqlMetal.exe" /server:. /database:NameOfDatabase /pluralize /code:ContextGenerated.cs /sprocs /views /functions

在 Linq to sql 中使用此函数的方法如下:

from s in context.Services
where context.Func_ConcatWithoutCollation(s.Description, s.Email) == "whatever"
select s

这对我很有帮助,也许其他人也会觉得有用。


1

LINQ to SQL没有为查询设置使用的排序规则的特定功能,因此它将始终使用数据库默认值。


0
一个解决方案可以是创建一个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查询中使用它,例如(linq-to-entities):

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接