.Net 字符串相等比较器类,其工作原理与 SQL 排序规则完全一样

问题描述 投票:0回答:1

我需要在具有唯一索引的字符串列的表中实现导入功能。为了访问数据库,我使用 EF Core 8。为了确保导入顺利运行,我删除了 C# 代码中的所有重复项,但导入仍然失败。

我进行了深入研究,发现了一个应该与 SQL Server 的行为相匹配的比较器:来自

CollationInfo.GetCollationInfo("Latin1_General_CI_AS").EqualityComparer
包的
Microsoft.SqlServer.SqlManagementObjects
。但当我比较时:

  CollationInfo.GetCollationInfo("Latin1_General_CI_AS").EqualityComparer.Equals("ß","SS")

我在尝试将此字符串导入数据库时遇到

false
,由于唯一约束,将会失败。

首先通过 EF 代码创建数据库。我调用

modelBuilder.UseCollation("Latin1_General_CI_AS");
以确保使用相同的排序规则,当我检查唯一索引时,它具有此排序规则集(以及数据库默认排序规则)。

有没有完全匹配 SQL 排序规则的 EqualityComparer?

.net sql-server entity-framework-core
1个回答
0
投票

由于您使用的是 EF8,您的目标框架必须是 .NET 8。根据这个问题,.NET 5 在字符串比较算法中引入了重大更改,您正在使用它的较新版本(基于 ICU)。

即使

ß
ss
被认为是相等的,因为
ß
仅在德语中使用,ICU 对
ß
ss
比较的处理也不同
。坦白说,我并不完全理解这个解释,但我想这是有充分理由的。

就我而言,在最新 Windows 10 上运行的 .NET 6 应用程序每次比较都会返回

false

var k1 = StringComparer.Create(new CultureInfo("en-US", false), CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType).Equals("ß", "SS"); 
var k2 = StringComparer.Create(new CultureInfo("de-DE", false), CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType).Equals("ß", "SS"); 
var k21 = StringComparer.Create(new CultureInfo("de-AT", false), CompareOptions.IgnoreCase | CompareOptions.IgnoreWidth | CompareOptions.IgnoreKanaType).Equals("ß", "SS");

除非我按照建议添加

CompareOptions.IgnoreNonSpace

您的 .NET 代码不起作用,因为

CollationInfo.GetCollationInfo("Latin1_General_CI_AS")
返回的比较器是在没有这个新的
CompareOptions.IgnoreNonSpace
解决方法的情况下创建的(顺便说一句,您使用的是旧版本的包,对吧?尝试更新到最新的 v170+)。

现在回到 MS SQL Server。我找不到 SQL Server 字符串比较在幕后如何工作的解释,但我认为它必须使用操作系统的函数才能获得最佳性能,或者尽可能模仿默认的 Windows 行为(即旧的基于 NLS 的行为)即使操作系统升级,也可以提供相同的一致结果。无论哪种方式,它的工作方式都与最新的 .NET 实现不同。

© www.soinside.com 2019 - 2024. All rights reserved.