PostgreSQL与EF Core 8土耳其字符不区分大小写搜索问题求解
在PostgreSQL 15 + EF Core 8中解决土耳其字符的不区分大小写搜索问题
问题根源
PostgreSQL的大小写转换、字符串比较逻辑依赖排序规则,默认规则未适配土耳其语的特殊大小写映射(I→ı、i→İ);EF Core默认字符串操作也未自动适配土耳其语规则,导致搜索结果不符合预期。
解决方案
1. 为数据库/列配置土耳其语排序规则
这是基础前提,确保PostgreSQL处理土耳其字符时使用正确的大小写转换逻辑。
新建表时指定排序规则
CREATE TABLE Products ( ID INT PRIMARY KEY, Name VARCHAR(255) COLLATE "tr_TR.utf8" );
修改现有列的排序规则
ALTER TABLE Products ALTER COLUMN Name TYPE VARCHAR(255) COLLATE "tr_TR.utf8";
2. EF Core查询适配方案
方案一:使用EF.Functions.Collate强制指定排序规则
在查询中显式指定土耳其语排序规则,让Contains操作按土耳其语逻辑执行:
var searchTerm = "milk"; // 支持"mılk"、"MILK"、"MİLK"任意形式 var result = Products .Where(p => EF.Functions.Collate(p.Name, "tr_TR.utf8") .Contains(EF.Functions.Collate(searchTerm, "tr_TR.utf8"))) .ToList();
方案二:自定义PostgreSQL函数+EF Core映射
如果需要更复用的逻辑,可以创建自定义函数:
- 在PostgreSQL中创建函数:
CREATE OR REPLACE FUNCTION turkish_contains(column_text text, search_text text) RETURNS boolean AS $$ BEGIN RETURN LOWER($1 COLLATE "tr_TR.utf8") LIKE '%' || LOWER($2 COLLATE "tr_TR.utf8") || '%'; END; $$ LANGUAGE plpgsql IMMUTABLE;
- 在EF Core的DbContext中映射该函数:
[DbFunction("turkish_contains")] public static bool TurkishContains(string column, string searchTerm) => throw new NotImplementedException("该函数已映射到PostgreSQL");
- 查询时直接调用:
var result = Products .Where(p => TurkishContains(p.Name, "milk")) .ToList();
3. 修复citext无效问题
默认citext未使用土耳其语排序规则,需创建自定义citext类型:
CREATE COLLATION "tr_TR.utf8" (LOCALE = 'tr_TR.utf8'); CREATE TYPE tr_citext AS citext COLLATE "tr_TR.utf8";
之后将列类型改为tr_citext,即可实现土耳其语大小写不敏感的字符串存储与比较。
验证用户测试案例
当列FullName配置tr_TR.utf8排序规则后,以下查询将正常返回结果:
SELECT p."FullName" FROM "Personnel" p WHERE LOWER(p."FullName") = LOWER('Elif dirik');
此时LOWER会按照土耳其语规则转换:Elif→elif,ELİF→elif,两者匹配。
内容的提问来源于stack exchange,提问作者Elif Sena
相关产品推荐
相关产品推荐

