如何通过EF Code First为PostgreSQL设置土耳其排序规则并解决查询问题
PostgreSQL土耳其语字符"İ"的EF LINQ查询问题及解决方案
问题背景
数据库存储包含土耳其语字符"İ"的记录(例如用户名为"İbrahim"),使用EF LINQ执行如下查询:
query = query.Where(r => r.User.FirstName.ToLower().Contains(fullName.ToLower()));
出现以下问题:
- 搜索"İbrahim"能返回正确结果,但搜索"ibrahim"无匹配结果
- 尝试传入土耳其文化信息调用
ToLower(culture)时触发异常 - 配置PostgreSQL排序规则时收到错误:
pg_default LC_COLLATE "C"; Npgsql.PostgresException (0x80004005):22023: new collation (C) is incompatible with the collation of the template database (English_United States.1252)
解决方案1:直接调用数据库的土耳其语大小写转换函数
利用EF.Functions调用PostgreSQL的LOWER函数,并指定土耳其语规则,避免客户端与数据库的文化差异:
var searchTerm = fullName; query = query.Where(r => EF.Functions.Lower(r.User.FirstName, "tr-TR") .Contains(EF.Functions.Lower(searchTerm, "tr-TR")));
注意:确保PostgreSQL已安装ICU扩展(多数现代版本默认自带),若未安装,先执行SQL:
CREATE EXTENSION IF NOT EXISTS icu;
解决方案2:重建数据库并配置列级土耳其语排序规则
之前的错误源于数据库模板排序规则与指定规则冲突,需重新创建数据库:
- 删除现有数据库,执行SQL创建带土耳其语排序规则的新库:
CREATE DATABASE your_db_name WITH TEMPLATE template0 LC_COLLATE 'tr_TR.UTF-8' LC_CTYPE 'tr_TR.UTF-8';
- 在EF模型配置中,为目标列指定土耳其语ICU排序规则:
modelBuilder.Entity<User>() .Property(p => p.FirstName) .UseCollation("tr-TR-x-icu");
配置完成后,LINQ查询可直接使用普通ToLower(),数据库会按土耳其语规则处理大小写匹配。
解决方案3:全局配置EF的土耳其语排序规则
若需全局应用土耳其语排序,在DbContext的OnConfiguring方法中设置:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql("your_connection_string", o => o.UseCollation("tr-TR-x-icu")); }
前提:数据库需按方案2的语句创建,确保基础排序规则兼容。
内容的提问来源于stack exchange,提问作者Yazan Al Khatib
相关产品推荐
相关产品推荐

