EF Core运行PostgreSQL查询时对UTF-8字符串生成错误字符问题
问题原因
你遇到的带重音UTF-8字符查询时被自动转换为无重音字符的问题,本质是PostgreSQL排序规则(collation)的默认配置问题,而非EF Core的参数编码错误。默认情况下多数PostgreSQL实例的数据库/列级排序规则设置为不区分重音(accent-insensitive),执行字符串匹配操作时会自动将带重音的字符转换为无重音版本处理。
你提供的问题复现代码:
query = query.Where(x => x.DisplayName != null && x.DisplayName.ToLower().Contains(slowUsername));
当slowUsername值为*"nghĩa"*时,默认排序规则下EF Core翻译后的SQL会按照无重音规则匹配,就会出现参数看起来被转换为"nghia"的现象。
问题现象截图:
解决方案
方案1:查询时临时指定区分重音的排序规则
直接在EF Core查询中通过EF.Functions.Collate指定区分重音的排序规则,PostgreSQL中常用的区分重音排序规则为ucs_basic或对应语言的UTF-8区分重音规则,修改后代码如下:
query = query.Where(x => x.DisplayName != null && EF.Functions.Collate(x.DisplayName.ToLower(), "ucs_basic").Contains(slowUsername));
如果希望该字段所有查询都默认区分重音,可以在模型配置时直接给列指定固定排序规则:
modelBuilder.Entity<你的实体类名称>() .Property(x => x.DisplayName) .UseCollation("ucs_basic");
方案2:修改数据库/列的默认排序规则
如果需要全库所有字符串查询默认区分重音,可以直接修改对应列或者整个数据库的默认排序规则:
- 首先查询当前数据库支持的所有排序规则,确认可选的区分重音规则:
SELECT * FROM pg_collation; - 修改对应列的默认排序规则:
ALTER TABLE 你的表名 ALTER COLUMN "DisplayName" TYPE text COLLATE "ucs_basic";
验证方法
你可以直接在PostgreSQL客户端执行如下SQL确认是否为排序规则导致的问题:
-- 区分重音规则下返回false,即不会匹配 SELECT 'nghĩa' LIKE '%nghia%' COLLATE "ucs_basic"; -- 默认不区分重音规则下返回true,即会自动转换重音匹配 SELECT 'nghĩa' LIKE '%nghia%' COLLATE "你当前的默认排序规则";
如果执行结果符合上述注释描述,即可确认问题根因是排序规则配置。
内容的提问来源于stack exchange,提问作者user17068846
相关产品推荐
相关产品推荐

