配置UseCollation后EF Core 5.0.9仍存在Unicode字符损坏问题
EF Core 5.0.x版本中,IsUnicode(false)配置会强制将实体对应字段的字符串参数标记为非Unicode的ANSI字符串类型,参数编码默认采用数据库全局默认排序规则对应的代码页,而非字段单独指定的排序规则对应的代码页。
你使用的Azure SQL Server默认全局排序规则通常为SQL_Latin1_General_CP1_CI_AS,对应代码页1252,不支持俄文等非西欧字符,因此参数在传输到数据库前就已经被转码为?,哪怕字段本身配置了UTF8排序规则也无法修复已经损坏的字符。
方案1(最推荐):升级EF Core版本
该问题已在EF Core 6.0及以上版本中正式修复,高版本EF Core会自动将字段配置的排序规则关联到对应参数,转码时采用排序规则对应的UTF8编码,原有实体映射配置无需修改即可正常运行。
方案2(兼容EF Core 5.x):调整实体映射逻辑
保留varchar UTF8字段存储结构的前提下,修改字段配置,让EF Core以Unicode格式传输参数,由SQL Server自动完成UTF8转码存储,不会额外占用存储空间,仅传输阶段的少量性能损耗可忽略:
builder.Entity<UsageStatistic>(p => { p.Property(prop => prop.Param) // 移除IsUnicode(false)配置,默认采用Unicode传输参数 .UseCollation("Latin1_General_100_BIN2_UTF8") .HasColumnType("varchar(255)") // 显式指定字段类型仍为varchar,保证存储结构不变 .HasMaxLength(255); }
方案3(兼容EF Core 5.x):自定义命令拦截器
如果必须保留IsUnicode(false)配置,可以实现DbCommandInterceptor,在SQL命令执行前手动将对应字段参数的编码修改为UTF8,并指定对应排序规则,实现复杂度略高于方案2。
这是EF Core 5.x的已知缺陷,不属于业务配置错误,问题根因就是非Unicode参数未继承字段级别的排序规则配置,错误使用全局默认代码页做转码,该修复已经合并到EF Core 6.0及后续所有正式版本中。
内容的提问来源于stack exchange,提问作者user2410689

