如何在.NET中排序,与SQL Server排序规则相同?

How to Sort in .NET Same as a SQL Server Collation?

提问人:John Saunders 提问时间:1/7/2011 最后编辑:John Saunders 更新时间:2/18/2011 访问量:3561

问:

我一直在对一些现有的存储过程做一些TDD。它们返回 XML,因此我一直在使用 LINQ to XML。

目前,我正在进行一项测试,以证明数据已正确排序。该测试在 XML 中导航,并创建一个匿名类型的 IEnumerable,其中包含应排序的三列。在此基础上,它通过对第一个 IEnumerable 进行排序来创建第二个 IEnumerable:

var sortedColumns = from g in columns
                    orderby g.ColumnA ascending,
                            g.ColumnB ascending,
                            g.ColumnC ascending
                    select g;

最后,它使用 SequenceEquals 断言排序的列与未排序的列相同。

当数据库排序规则与当前排序规则不同时,就会出现问题。具体而言,.NET 将 ColumnB 中的“W-”放在“Wa”之前。

有没有办法按照与任意 SQL Server 排序规则相同的顺序进行排序?如果没有,那么我将如何按照与SQL_Latin1_General_CP1_CI_AS相同的顺序进行排序?

sql-server linq-to-xml 排序规则

答:

0赞 MicSim 1/7/2011 #1

LINQ-to-SQL 不支持直接使用排序规则。如果要实现特殊排序,则必须在本地获取数据,将其转换为列表(或其他内容),然后自己进行排序。

有关进一步参考,请参阅以下两个链接:

评论

0赞 John Saunders 1/7/2011
对不起,我想我不清楚。我没有使用 LINQ to SQL - 我在来自 SQL Server 的某些 XML 上使用 LINQ to XML。
0赞 MicSim 1/7/2011
哦,没关系。我就在这里做出这个回应,也许它对其他人有帮助。
0赞 Brett 1/7/2011 #2

我已经从 use-own-icomparert-with-linq-orderby 中删除了它。

        MyComparer comparer = new MyComparer();
        items = items.OrderByDescending(
                  x => property.GetValue(x), comparer).ToList();
        break;

您可以根据需要创建自定义比较器。(你可能需要一个具体类型而不是一个匿名类型来获得你的结果 - 我还没有真正测试过这个)。

评论

0赞 John Saunders 1/7/2011
谢谢,但哪个比较器?有没有一种通用的方法来创建与任何 SQL Server 排序规则匹配的比较器,或者您能否向我展示要像SQL_Latin1_General_CP_CI_AI一样进行比较的代码?
0赞 Brett 1/8/2011
我不相信有用于 SQL Server 排序规则的开箱即用的 IComparer。您需要创建一个实现 IComparer 的类,并自行进行适当的比较。
0赞 Brett 1/8/2011
(续..)我并不是说它会很:)显然,如果你特别想要SQL_Latin1_General_CP1_CI_AI,你可以执行 ToLower() (CI)。我猜是重音(AI)的搜索/替换?这比我研究的要远一点......
4赞 Remus Rusanu 1/8/2011 #3

如果是 Windows 排序规则,则归结为设置适当的区域设置和排序顺序,如排序顺序标识符,在 .Net 世界中,它采用当前设置的 UI 区域性。

如果是 SQL 排序规则,则稍微复杂一些。如果您使用 VARCHAR,则您将失去锁定。对于NVARCHAR来说,还是有一些希望的。请参阅将 SQL 排序规则与 Windows 排序规则进行比较

SQL 排序规则的排序规则 非 Unicode 数据与 提供的任何排序例程 Microsoft Windows操作系统 系统;但是,排序 Unicode 数据与 特定版本的 Windows 排序规则。因为比较 非 Unicode 和 Unicode 数据的规则 是不同的,当你使用 SQL 您可能会看到不同的排序规则 相同结果的比较结果 字符,具体取决于 基础数据类型。例如,如果 您正在使用 SQL 排序规则 “SQL_Latin1_General_CP1_CI_AS”, 非 Unicode 字符串“a-c”小于 字符串“ab”,因为连字符 (“-”) 排序为单独的 “b”之前的字符。 但是,如果转换这些字符串 更改为 Unicode,然后您执行相同的操作 比较,Unicode 字符串 N'a-c' 被认为大于 N'ab' 因为 Unicode 排序规则使用 忽略连字符的“单词排序”。

为了您的目的(TDD),我建议您远离可疑字符,例如连字符,或者一个接两个(德语ss问题),或大写(土耳其语colliton问题),(西班牙语排序规则问题)等...坚持使用正确排序的一小部分字符,例如 .我是认真的。-sIsha,A,b,B

评论

1赞 John Saunders 1/8/2011
不幸的是,我们不能使用干净的数据 - 我必须使用那里的东西。
0赞 Remus Rusanu 1/8/2011
将 SQLite 或 SQL CE 用于测试存储怎么样?它们有排序规则。
0赞 John Saunders 1/8/2011
或者,“激进的概念”,使用“单元测试数据库”进行单元测试,而不是我在集成环境中测试应用程序时使用的同一数据库。嗯。
0赞 John Saunders 2/18/2011
对不起,花了这么长时间才接受你的回答。你让我走上了正确的轨道。自 1 月以来,我所有与数据库相关的单元测试都在事务中插入测试数据(可能先截断表),然后在测试结束时回滚。我正在研究“datadude”数据库单元测试,它首先部署数据库的干净副本,然后通过数据生成计划填充它。
1赞 Jason Kleban 8/27/2013
那么,如何使用 .Net Comparer 来模拟 Windows“SQL_Latin1_General_CP1_CI_AS”排序规则呢?我没有找到任何关于这个主题的好信息(除了这个答案)。如果可以避免它并且仍然获得 100% 准确的结果(相对于 sql server 的实现),我不想必须加载 sqlparser 库来使用它的预构建比较器。
1赞 Samuel Neff 2/18/2011 #4

编写一个自定义实现,该实现实际上调用 SQL Server,以比较它被要求比较的两个值中的每一个。IComparer

它会很慢,有点傻,但它会完全按照你的要求去做。

或者,如果您只关心精确复制一个特定的排序规则序列,而不关心任何随机排序规则,则编写一个一次性例程来调用 SQL Server,并按照 SQL Server 放置字符的顺序生成所有字符的集合,并使用该集合来生成自定义实现,然后该实现将匹配 SQL Server 的序列,而无需在运行时调用 SQL Server。IComparer

评论

0赞 John Saunders 2/18/2011
谢谢你的回答。我希望我能给它投两次赞成票。我会把它标记为公认的答案,除了 Remus Rusanu 的答案实际上让我走上了正确的道路——我认为这是处理所有这些问题的正确方法——创建你自己的数据,要么在一个干净的数据库中,要么在事务中这样做,并在测试结束时回滚。