另一项每次只返回一页记录的技术是创建 SQL 语句,把 TOP 谓词和嵌入式 SELECT 语句的使用结合在一起。此技术并不依赖于存在一种可唯一标识每一行的办法。使用这项技术的第一步是把所需页的数量与页大小相乘。然后将结果传递给 SQL Query 的 TOP 谓词,该查询以升序排列。再把此查询嵌入到另一个查询中,后者从降序排列的嵌入式查询结果中选择 TOP 页大小。实质上,返回的是嵌入式查询的最后一页。例如,要返回查询结果的第三页(页大小是 10),应该书写如下所示的命令:
SELECT TOP 10 * FROM (SELECT TOP 30 * FROM Customers ORDER BY Id ASC) AS Table1 ORDER BY Id DESC注意,从查询中返回的结果页以降序显示。如果需要,应该重新排序。
•
如果数据不经常变动,可以在 DataSet 中本地维护一个记录缓存,以此提高性能。例如,可以在本地 DataSet 中存储 10 页有用的数据,并且只有当用户浏览超出缓存第一页和最后一页时,才从数据源中查询新数据。
有关更多信息,请参阅 .NET Data Access Architecture Guide。
用架构填充 DataSet
当用数据填充 DataSet 时,DataAdapter.Fill 方法使用 DataSet 的现有架构,并使用从 SelectCommand 返回的数据填充它。如果在 DataSet 中没有表名与要被填充的表名相匹配,Fill 方法就会创建一个表。默认情况下,Fill 仅定义列和列类型。
通过设置 DataAdapter 的 MissingSchemaAction 属性,可以重写 Fill 的默认行为。例如,要让 Fill 创建一个表架构,并且还包括主键信息、唯一约束、列属性、是否允许为空、最大列长度、只读列和自动增量的列,就要把 DataAdapter.MissingSchemaAction 指定为 MissingSchemaAction.AddWithKey。或者,在调用 DataAdapter.Fill 前,可以调用 DataAdapter.FillSchema 来确保当填充 DataSet 时架构已到位。
对 FillSchema 的调用会产生一个到服务器的额外行程,用于检索附加架构信息。为了获得最佳性能,需要在调用 Fill 之前指定 DataSet 的架构,或者设置 DataAdapter 的 MissingSchemaAction。
使用 CommandBuilder 的最佳实践
假设 SelectCommand 执行单一表 SELECT,CommandBuilder 就会以 DataAdapter 的 SelectCommand 属性为基础自动生成 DataAdapter 的 InsertCommand、UpdateCommand、和 DeleteCommand 属性。下面是为获得最佳性能而使用 CommandBuilder 的一些技巧。
•CommandBuilder 的使用应该限制在设计时或即席方案中。生成 DataAdapter 命令属性所必需的处理会影响性能。如果预先知道 INSERT/UPDATE/DELETE 语句的内容,就显式设置它们。一个比较好的设计技巧是,为 INSERT/UPDATE/DELETE 命令创建存储过程并显式配置 DataAdapter 命令属性以使用它们。
•
CommandBuilder 使用 DataAdapter 的 SelectCommand 属性确定其他命令属性的值。如果 DataAdapter 的 SelectCommand 本身曾经更改过,确保调用 RefreshSchema 以更新命令属性。
•
如果 DataAdapter 命令属性为空(命令属性默认情况下为空),CommandBuilder 仅仅为它生成一条命令。如果显式设置了命令属性,CommandBuilder 不会重写它。如果希望 CommandBuilder 为以前已经设置过的命令属性生成命令,就把命令属性设置为空。
批处理 SQL 语句
很多数据库支持把多条命令合并或批处理成一条单一命令执行。例如,SQL Server 使您可以用分号 (;) 分隔命令。把多条命令合并成单一命令,能减少到服务器的行程数,并提高应用程序的性能。例如,可以把所有预定的删除在应用程序中本地存储起来,然后再发出一条批处理命令调用,从数据源删除它们。
虽然这样做确实能提高性能,但是,当对 DataSet 中的数据更新进行管理时,可能会增加应用程序的复杂性。要保持简单,可能要在 DataSet 中为每个 DataTable 创建一个 DataAdapter。
用多个表填充 DataSet