C# 中的带 SelectDistinct 的 DataTable
允许您对 DataTable 执行 Distinct 查询

引言
VS.NET 提供的 ADO.NET 对象允许您从数据库或其他源检索数据,并将此数据存储在称为 DataSet
或 DataTable
的对象中。实际上,DataSet
是 DataTable
的集合。DataTable
提供的一个常用方法是 Select()
。它允许开发人员对 DataTable
执行简单的筛选,并以 DataRow
集合的形式返回结果。我最近发现 .NET 中有一种执行 DISTINCT 查询的方法。DataView
对象公开了一个名为 ToTable()
的方法。此方法接受一个布尔标志来确定是否执行 DISTINCT 以及您希望基于哪些字段执行 DISTINCT。虽然此方法确实从 DataTable
返回了 DISTINCT 行,但似乎它仅适用于小型记录集。当用于包含 40,000 行的 DataTable
时,大约需要 18 秒。我可以想象,对于一百行左右的数据,它的速度会非常快。但是,如果您想对大型表执行 DISTINCT,目前没有更好的方法了。直到现在。
背景
我最近遇到了一个问题,服务器处理用户请求的速度太慢,无法处理返回的大量数据。我需要检索数据并在内存中完全操作数据,以减少访问 SQL Server 的次数。一个主要的障碍是我需要对我的 DataTable
应用 DISTINCT 查询。我很快就发现这是不可能的。微软有一篇 文章 演示了一个简单的 DISTINCT,但它不够健壮,无法满足我的需求。它只允许指定一个列,而我需要根据不同时间的不同数量的列。我反复修改了微软的示例,直到我最终能够处理多个列、过滤/条件和排序。
Using the Code
在该对象内部,只有一个主要方法称为 SelectDistinct()
。它重载了大约十次,以便在编码时提供灵活性。要使用我的对象,只需实例化对象并调用 SelectDistinct
方法。
我包含了一个演示应用程序,允许您指定 SQL 连接字符串和查询或存储过程,以便您可以测试 SelectDistinct
对象的性能和准确性。
clsDSHcs dsh = new clsDSHcs(dt);
DataTable dt2 = dsh.SelectDistinct(Fields,Filter,Sort);
//Or
clsDSHcs dsh = new clsDSHcs();
DataTable dt2 = dsh.SelectDistinct(dt,Fields,Filter,Sort);
代码示例假设“dt
”已被定义并已填充。请注意,在两种情况下,“dsh
”对象实际上都会保留 datatable
的副本,并且可以通过 .Table
属性进行访问。
完成该对象后,我发现它可以运行得更快。我最初是使用两个 DataTable
来完成的,只取唯一的行并将它们放入新表中,然后从对象中返回该表。令我沮丧的是,这比任何人想象的都要慢。
**更新** - 基于 srkinyon 提供给我的一些代码,我重写了该对象以整合他的一些想法,并重新组织和删除了所有不再必要的内容。这包括之前提到的哈希。现在,该对象能够在约 0.6 秒内对超过 40,000 行的 DataTable
执行 DISTINCT。这比以前快了约 3 倍。现在这很快了。不过,我得承认我的代码中也有一些小的冗余。尽管如此,大部分性能提升似乎来自于我现在将 datacolumn
值存储为它们本身的“object
”类型,而不是将它们转换为 string
然后进行哈希。我还得承认,哈希不足以用于 DISTINCT。所以,向 srkinyon 致敬。如果还有其他人能做得更快或更好,请不要犹豫。我还为了好玩添加了几个额外的属性。一个是 RecordCount
,这应该是显而易见的。另外,ElapsedTime
,它存储了上一次 Distinct 调用所花费的总时间。这有点浪费时间,但我想知道对象的速度有多快。
关注点
在我的开发周期中,我发现即使是很小的事情也会极大地拖慢速度。甚至是 .Trim()
或 .Split()
。所以请明智地使用它们。
另外,我也用 VB 编写了同一个对象,这个对象也可以在这个网站上找到,这样您就可以两全其美了 :) 顺便说一句,两种语言的速度之间没有实际区别。
历史
- 2007年10月4日:首次发布
- 2007年10月11日:文章更新