|
突岱浅>薮蟆?
使用ADO
实现分页的另一个选项是利用基于COM的ADO进行分页。这种方法的目标是获得访问服务器光标。服务器光标通过ADO Recordset对象显示。可以把Recordset光标的位置设置到adUseServer中。如果你的OLE DB供应器支持这种设置(如SQLOLEDB那样),就可以使用服务器光标。这样就可以利用光标直接导航到起始记录,而不需要将所有数据传过网络进入访问数据的用户代码中。
这种方法有下面两个缺点:
在大多数情况下,可能需要将返回到Recordset对象中的记录翻译成DataSet中的内容,以便在客户管理的代码中使用。虽然OleDbDataAdapter确实在获取ADO Recordset对象并把它翻译成Dataset时过载了Fill方法,但是并没有利用特殊记录进行开始与结束操作的功能。唯一现实的选项是把开始记录移动到Recordset对象中,循环每个记录,然后手工拷贝数据到手工生成的新Dataset中。这种操作,尤其是利用COM Interop调用,其优点可能不仅仅是不需要在网络上传输多余的数据,尤其对于小的DataSet更明显。
从服务器输出所需数据时,将保持连接和服务器光标开放。在数据库服务器上,光标的开放与维护需要昂贵的资源。虽然该选项提高了性能,但是由于为延长的时间两消耗服务器资源,从而也有可能降低可扩展性。
提供手工实现
在本部分中讨论的数据分页的最后一个选项是利用存储过程手工实现应用程序的分页功能。对于包含唯一关键字的表格,实现存储过程相对容易一些。而对于没有唯一关键字的表格(也不应该有许多关键字),该过程会相对复杂一些。
带有唯一关键字的表格的分页
如果表格包含一个唯一关键字,就可以利用WHERE条款中的关键字创建从某个特殊行起始的结果设置。这种方法,与用来限制结果设置大小的SET ROWCOUNT状态是相匹配的,提供了一种有效的分页原理。这一方法将在下面存储的代码中说明:
CREATE PROCEDURE GetProductsPaged
@lastProductID int,
@pageSize int
AS
SET ROWCOUNT @pageSize
SELECT *
FROM Products
WHERE [standard search criteria]
AND ProductID > @lastProductID
ORDER BY [Criteria that leaves ProductID monotonically increasing]
GO
这个存储过程的调用程序仅仅维护LastProductID的值,并通过所选的连续调用之间的页的大小增加或减小该值。
不带有唯一关键字的表格的分页
如果需要分页的表格没有唯一关键字,可以考虑添加一个--比如利用标识栏。这样就可以实现上面讨论的分页方案了。
只要能够通过结合结果记录中的两个或更多区域来产生唯一性,就仍然有可能实现无唯一关键字表格的有效分页方案。
比如,考察下列表格: Col1 Col2 Col3 Other columns…
A 1 W …
A 1 X .
A 1 Y .
A 1 Z .
A 2 W .
A 2 X .
B 1 W …
B 1 X .
对于该表,结合Col 、Col2 和Col3就可能产生一种唯一性。这样,就可以利用下面存储过程中的方法实现分布原理:
CREATE PROCEDURE RetrieveDataPaged
@lastKey char(40),
@pageSize int
AS
SET ROWCOUNT @pageSize
SELECT
Col1, Col2, Col3, Col4, Col1 Col2 Col3 As KeyField
FROM SampleTable
WHERE [Standard search criteria]
AND Col1 Col2 Col3 > @lastKey
ORDER BY Col1 ASC, Col2 ASC, Col3 ASC
GO
客户保持存储过程返回的keyField栏的最后值,然后又插入回到存储过程中以控制表的分页。
虽然手工实现增加了数据库服务器上的应变,但它避免了在网络上传输不必要的数据。性能测试表明在整个应变水平中这种方法都工作良好。然而,根据站点工作所涉及的数据分页功能的多少,在服务器上进行手工分页可能影响应用程序的可扩展性。应该在所在环境中运行性能测试,为应用程序找到最合适的方法。
附录
如何为一个.NET类启用对象结构
要利用Enterprise (COM )Services为对象结构启用.NET管理的类,需要执行下列步骤:
从位于System. Enterprise Services名字空间中的Serviced Component中导出所需类。
using System.EnterpriseServices;
public class DataAccessComponent : ServicedComponent
为该类添加Construction Enabled属性,并合理地指定缺省结构字符串,该缺省值保存在COM 目录中,管理员可以利用组件服务微软管理控制台(MNC)的snap-in来维护该缺省值。
[ConstructionEnabled(Default="default DSN")]
public class DataAccessComponent : ServicedComponent
提供虚拟Construct方法的替换实现方案。该方法在对象语言构造程序之后调用。在COM目录中保存的结构字符串是该方法的唯一字符串。
public override void Construct( string constructString )
{
// Construct method is called next after constructor.
// The configured DSN is supplied as the single argument
}
通过Assembly key文件或Assembly key Name属性为该汇编提供一个强名字。任何用COM 服务注册的汇编必须有一个强名字。关于带有强名字汇编的更多信息,参考:http://msdn.microsoft.com/library/en-us/cpguide/html/cpconworkingwithstrongly- namedassemblies.Asp。
[assembly: AssemblyKeyFile("DataServices.snk")]
为支持动态注册,可以利用汇编层上的属性ApplicationName和Application Action分别指定用于保持汇编元素和应用程序动作类型的COM 应用程序的名字。关于汇编注册的更多信息,参考: http://msdn.microsoft.com/library/en-us/cpguide/html/cpconregisteringserviced components.asp。
// the ApplicationName attribute specifies the name of the
// COM Application which will hold assembly components
[assembly : ApplicationName("DataServices")]
// the ApplicationActivation.ActivationOption attribute specifies
// where assembly components are loaded on activation
// Library : components run in the creator's process
// Server : components run in a system process, dllhost.exe
[assembly: ApplicationActivation(ActivationOption.Library)]
下列代码段是一个叫做DataAccessComponent的服务组件,它利用COM 结构字符串来获得数据库连接字符串。
using System;
using System.EnterpriseServices;
// the ApplicationName attribute specifies the name of the
// COM Application which will hold assembly components
[assembly : ApplicationName("DataServices")]
// the ApplicationActivation.ActivationOption attribute specifies
// where assembly components are loaded on activation
// Library : components run in the creator's process
// Server : components run in a system process, dllhost.exe
[assembly: ApplicationActivation(ActivationOption.Library)]
// Sign the assembly. The snk key file is created using the
// sn.exe utility
[assembly: AssemblyKeyFile("DataServices.snk")]
[ConstructionEnabled(Default="Default DSN")]
public class DataAccessComponent : ServicedComponent
{
private string connectionString;
public DataAccessComponent()
{
// constructor is called on instance creation
}
public override void Construct( string constructString )
{
// Construct method is called next after constructor.
// The configured DSN is supplied as the single argument
this.connectionString = constructString;
}
}
如何利用SqlDataAdapter来检索多个行
下面的代码说明如何利用SqlDataAdapter对象发出一个生成Data Set或Datatable的命令。它从SQL Server Northwind数据库中检索一系列产品目录。
using System.Data;
using System.Data.SqlClient;
public DataTable RetrieveRowsWithDataTable()
{
using ( SqlConnection conn = new SqlConnection(connectionString) )
{
SqlCommand cmd = new SqlCommand("DATRetrieveProducts", conn);
cmd.CommandType = CommandType.StoredProcedure;
SqlDataAdapter da = new SqlDataAdapter( cmd );
DataTable dt = new DataTable("Products");
da.Fill(dt);
return dt;
}
}
按下列步骤利用SqlAdapter生成DataSet或DataTable:
创建SqlCommand对象启用存储过程,并把它与SqlConnection对象(显示的)或连接字符串(未显示)相联系。
创建一个新的SqlDataAdapter对象,并把它SqlCommand对象相联系。
创建DataTable(或者DataSet)对象。利用构造程序自变量命名DataTable.
调用SqlData Adapter对象的Fill方法,把检索的行转移到DataSet或Datatable中。
如何利用SqlDataReader检索多个行
下列代码说明了如何利用SqlDataReader方法检索多行:
using System.IO;
using System.Data;
using System.Data.SqlClient;
public SqlDataReader RetrieveRowsWithDataReader()
{
SqlConnection conn = new SqlConnection(
"server=(local);Integrated Security=SSPI;database=northwind");
SqlCommand cmd = new SqlCommand("DATRetrieveProducts", conn );
cmd.CommandType = CommandType.StoredProcedure;
try
{
conn.Open();
// Generate the reader. CommandBehavior.CloseConnection causes the
// the connection to be closed when the reader object is closed
return( cmd.ExecuteReader( CommandBehavior.CloseConnection ) );
}
catch
{
conn.Close();
throw;
}
}
// Display the product list using the console
private void DisplayProducts()
{
SqlDataReader reader = RetrieveRowsWithDataReader();
while (reader.Read())
{
Console.WriteLine("{0} {1} {2}",
reader.GetInt32(0).ToString(),
reader.GetString(1) );
}
reader.Close(); // Also closes the connection due to the
// CommandBehavior enum used when generating the reader
}
按下列步骤利用SqlDataReader检索多行:
创建用于执行存储的过程的SqlCommand对象,并把它与SqlConnection对象相联系。
打开链接。
通过调用SqlCommand对象的Excute Reader方法生成SqlDataReader对象。
从流中读取数据,调用SqlDataReader对象的Read方法来检索行,并利用分类的存取程序方法(如GetIut 32和Get String方法)检索列的值。
完成读取后,调用Close方法。
如何利用XmlReader检索多个行
可以利用SqlCommand对象生成XmlReader对象,它提供对XML数据的基于流的前向访问。该命令(通常是一个存储的过程)必须生成一个基于XML的结果设置,它对于SQL Server2000通常是由带有有效条款FOR XML的SELECT状态组成。下列代码段说明了这种方法:
public void RetrieveAndDisplayRowsWithXmlReader()
{
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("DATRetrieveProductsXML", conn );
cmd.CommandType = CommandType.StoredProcedure;
try
{
conn.Open();
XmlTextReader xreader = (XmlTextReader)cmd.ExecuteXmlReader();
while ( xreader.Read() )
{
if ( xreader.Name == "PRODUCTS" )
{
string strOutput = xreader.GetAttribute("ProductID");
strOutput = " ";
strOutput = xreader.GetAttribute("ProductName");
Console.WriteLine( strOutput );
}
}
xreader.Close();
}
[3] [4] [5] [6] [7] [8] [9] [10]
上一页 [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] 下一页
|