案呢?我发现,当客户端需要借助 group-by 函数及各种过滤器来组建一个复杂的“主从复合结构”(master/detail) 视图时,本方案是一个不错的选择。顺便提一句,此时采用多个不同而相关的表是非常有效的,ADO.NET 也为此提供了不少优化特性。 我们来讨论具体操作。以下代码示范了它的主要流程: Function SplitData(ByVal ds As DataSet) As DataSet Dim _dataset As New DataSet()
'''' Make a full worker copy of the DataSet _dataset = ds.Copy()
CreateCustomers(_dataset, ds) CreateEmployees(_dataset, ds)
'''' Remove columns from Orders(companyname [2] and lastname [4]) _dataset.Tables("Orders").Columns.RemoveAt(1) _dataset.Tables("Orders").Columns.RemoveAt(3)
Return _dataset End Function 代码首先完整地复制了 DataSet 对象(ds),以它作为新 DataSet 对象(_dataset) 中的Orders 表。接下来,代码又在新 DataSet 对象中动态添加了 customers 表和 employees 表。最后,它又从新 DataSet 对象的 Orders 表中删除了其它两个子表所包含的列。下图显示了新 DataSet 对象中 customers 表的内容。瞧,它只留下了 Orders 表中 (所有) 订单的客户 ID 和公司名两列。由于这两个表都有 customerid 列,故它们仍然可以建立关系。
图 3 . 根据第一次查询的返回结果新生成的 Customers 表
下面来简单谈谈用于创建和填充 customers 表与 employees 表所必需的代码。 一开始,你必须调用 clone 方法克隆原先的订单表以创建一个新的 DataTable 对象。与Copy 方法不同,Clone 方法仅仅复制元数据(metadata)。由于 DataTable 接口不允许克隆单个列,所以本方法是生成对等表的最简单途径。然而,这样生成的表将包含某些多余列,我们必须删除之。 只要分析第一个 DataSet 对象的结构,你就会发现 customerid 列和 companyname 列正是返回结果集的第一列和第二列。 Dim _customers As DataTable = orig.Tables("Orders").Clone() _customers.TableName = "Customers"
'''' Remove unneeded columns Dim i As Integer For i = 2 To _customers.Columns.Count - 1 _customers.Columns.RemoveAt(2) Next 建立表结构之后,还得载入数据。然而,在 Orders 表中可能多次出现同一个提交者。此外,你必须对源 DataSet 对象中的数据加以过滤。好在 Orders 表已经根据 customerid 列进行排序,所以你只要循环遍历所有行,从中选出符合条件者即可。 Dim row As DataRow Dim customerKey As String = "" For Each row In _dataset.Tables("Orders").Rows '''' Already sorted by CustomerID If customerKey <> row("customerid") Then '''' select distinct _customers.ImportRow(row) customerKey = row("customerid") End If Next
'''' Add to the DataSet _dataset.Tables.Add(_customers) ImportRow 是从数据库导出指定行到新表的最快途径。通常,ImportRow 方法会根据模式 (schema) 的要求来挑选被导出的列。 原则上,employeess 表的创建和 customers 表的创建大体相同。当然了,你应该删除的列有所不同。从 Orders 表的结构来分析,我们必须保留第 3 列与第 4 列。下列代码首先删除第1列和第2列,然后用一个循环解决其它列。 Dim _employees As DataTable = orig.Tables("Orders").Clone() _employees.TableName = "Employees"
'''' Remove unneeded columns _employees.Columns.RemoveAt(0) _employees.Columns.RemoveAt(0) Dim i As Integer For i = 2 To _employees.Columns.Count - 1 _employees.Columns.RemoveAt(2) Next 最后,你还必须清除 employees 表中的重复行。在本例中,对 Orders 表的排序有助于简化该操作。你可以先创建 Orders 表的已排序视图(sorted view),然后循环遍历所有行。 Dim employeeKey As Integer = 0 Dim view As DataView = New DataView(_dataset.Tables("Orders")) view.Sort = "employeeid"
Dim rowView As DataRowView For Each rowView In view If employeeKey <> Convert.ToInt32(rowView("employeeid")) Then '''' select distinct _employees.ImportRow(rowView.Row) employeeKey = Convert.ToInt32(rowView("employeeid")) End If Next
'''' Add to the DataSet _dataset.Tables.Add(_employees) 总结 本文示范了一个复杂的 SQL 查询实例,并讨论了 3 种提高其效率的方案。不得不承认,经典的 ADO 对于此类问题的解决帮助有限,而 ADO.NET 却能让你构造一种功能强大的离线数据对象模型以提高程序性能。本文提到了几种解决方案,究竟哪种是最佳选择?很难说。影响运行效率的因素非常多,比如:网络的有效带宽,数据的继承一致性,程序对数据稳定性的要求,等等。为了确定最佳方案,你就必须逐一尝试各种方案,分别测试其性能。 原文见 http://msdn.microsoft.com/library/en-us/dndive/html/data06132002.asp
上一页 [1] [2] |