【参加讨论】服务器端数据介绍
数据访问是任何实际应用程序的核心部分,而 ASP.NET 提供了一套丰富的控件,这些控件与公共语言运行库中提供的托管数据访问 API 很好地集成在一起。本节多次演练同一个示例,该示例使用 ASP.NET DataGrid 控件绑定到 SQL 查询的结果和 XML 数据文件。本节假定您熟悉数据库基础知识和 SQL 查询语言。
服务器端数据访问很独特,因为 Web 页基本上是无状态的。当试图执行事务时,如插入或更新从数据库检索的数据集中的记录时,这向我们提出了某些困难的挑战。正如将在本节中看到的,DataGrid 控件可以帮助应付这些挑战,使您得以更多地集中在应用程序逻辑上,对状态管理和事件处理的具体细节则不用考虑太多。
连接、命令和数据集
公共语言运行库为数据密集的应用程序开发提供了完整的托管数据访问 API 集。这些 API 帮助抽象数据并用一致的方法表示数据,与实际的数据源(SQL Server、OLEDB、XML 等)无关。最常使用的对象基本上有三种:连接、命令和数据集。
- 连接表示与某些数据存储区(如 SQL Server 或 XML 文件)的物理连接。
- 命令表示从数据存储区检索(选择)或对数据存储区进行操作(插入、更新、删除)的指令。
- 数据集表示应用程序使用的实际数据。注意,数据集总是同它们的源连接和数据模型断开并可独立修改。不过,数据集的更改可以很容易与起始数据模型相协调。
有关公共语言运行库中托管数据访问解决方案的更详细演练,请阅读本教程的 ADO.NET 概述一节。
访问基于 SQL 的数据
应用程序一般需要对 SQL 数据库执行一个或多个选择、插入、更新或删除查询。下表显示上述每个查询的示例。
| 查询 |
示例 |
| 简单选择 |
SELECT * from Employees WHERE FirstName = 'Bradley'; |
| 联接选择 |
SELECT * from Employees E, Managers M WHERE E.FirstName = M.FirstName; |
| 插入 |
INSERT into Employees VALUES ('123-45-6789','Bradley','Millington','Program Manager'); |
| 更新 |
UPDATE Employees SET Title = 'Development Lead' WHERE FirstName = 'Bradley'; |
| 删除 |
DELETE from Employees WHERE Productivity < 10; |
为了使页能够访问执行 SQL 数据访问所需的类,必须将 System.Data 和 System.Data.SqlClient 命名空间导入到页中。
<%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
若要对 SQL 数据库执行选择查询,请创建与数据库的 SqlConnection,传递连接字符串,然后构造包含查询语句的 SqlDataAdapter 对象。若要用查询结果填充 DataSet 对象,请调用命令的 Fill 方法。
SqlConnection myConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
SqlDataAdapter myCommand = new SqlDataAdapter("select * from Authors", myConnection);
DataSet ds = new DataSet();
myCommand.Fill(ds, "Authors");
Dim myConnection As New SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes")
Dim myCommand As New SqlDataAdapter("select * from Authors", myConnection)
Dim ds As New DataSet()
myCommand.Fill(ds, "Authors")
var myConnection:SqlConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
var myCommand:SqlDataAdapter = new SqlDataAdapter("select * from Authors", myConnection);
var ds:DataSet = new DataSet();
myCommand.Fill(ds, "Authors");
|
| C# |
VB |
JScript |
|
正如本节前面所提到的,使用数据集的好处是它为您提供了断开连接的数据库视图。可以在应用程序中操作数据集,然后在以后协调更改和实际的数据库。对于长期运行的应用程序,这通常是最好的方法。对于 Web 应用程序,通常对每个请求执行短操作(一般只是显示数据)。通常不需要在一系列请求间保持 DataSet 对象。对于这类情况,可以使用 SqlDataReader。
SqlDataReader 对从 SQL 数据库检索的数据提供仅向前的只读指针。若要使用 SqlDataReader,请声明 SqlCommand 而不是 SqlDataAdapter。SqlCommand 公开返回 SqlDataReader 的 ExecuteReader 方法。还请注意,当使用 SqlCommand 时,必须显式打开和关闭 SqlConnection。调用 ExecuteReader 后,SqlDataReader 可以绑定到 ASP.NET 服务器控件,正如将在下一节看到的。
SqlConnection myConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
SqlCommand myCommand = new SqlCommand("select * from Authors", myConnection);
myConnection.Open();
SqlDataReader dr = myCommand.ExecuteReader();
...
myConnection.Close();
Dim myConnection As SqlConnection = New SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes")
Dim myCommand As SqlCommand = New SqlCommand("select * from Authors", myConnection)
myConnection.Open()
Dim dr As SqlDataReader = myCommand.ExecuteReader()
...
myConnection.Close()
var myConnection:SqlConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
var myCommand:SqlCommand = new SqlCommand("select * from Authors", myConnection);
myConnection.Open();
var dr : SqlDataReader;
dr = myCommand.ExecuteReader();
...
myConnection.Close();
|
| C# |
VB |
JScript |
|
当执行不要求返回数据的命令(如插入、更新和删除)时,也使用 SqlCommand。该命令通过调用 ExecuteNonQuery 方法发出,而该方法返回受影响的行数。注意当使用 SqlCommand 时,必须显式打开连接;SqlDataAdapter 自动为您处理如何打开连接。
SqlConnection myConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
SqlCommand myCommand = new SqlCommand(
"UPDATE Authors SET phone='(800) 555-5555' WHERE au_id = '123-45-6789'",
myConnection);
myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
Dim myConnection As New SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes")
Dim myCommand As New SqlCommand( _
"UPDATE Authors SET phone='(800) 555-5555' WHERE au_id = '123-45-6789'", _
myConnection)
myCommand.Connection.Open()
myCommand.ExecuteNonQuery()
myCommand.Connection.Close()
var myConnection:SqlConnection = new SqlConnection("server=(local)\NetSDK;database=pubs;Trusted_Connection=yes");
var myCommand:SqlCommand = new SqlCommand(
"UPDATE Authors SET phone='(800) 555-5555' WHERE au_id = '123-45-6789'",
myConnection);
myCommand.Connection.Open();
myCommand.ExecuteNonQuery();
myCommand.Connection.Close();
|
| C# |
VB |
JScript |
|
重要说明:始终记住在页完成执行之前关闭与数据模型的连接。如果不关闭连接,则可能会在等待页实例被垃圾回收处理期间不经意地超过连接限制。
将 SQL 数据绑定到 DataGrid
下面的示例显示一个绑定到 DataGrid 控件的简单选择查询。DataGrid 呈现包含 SQL 数据的表。
与“数据绑定”节中显示的 DropDownList 一样,DataGrid 控件也支持 DataSource 属性。该属性除了采用 DataSet 外,还采用 IEnumerable 或 ICollection。可以通过将 DataSet 中包含的表的 DefaultView 属性分配给希望在 DataSet 中使用的表名来使用 DataSet。DefaultView 属性表示 DataSet 中表的当前状态,包括应用程序代码所做的任何更改(例如,行删除或值更改)。设置了 DataSource 属性后,调用 DataBind() 填充控件。
MyDataGrid.DataSource=ds.Tables["Authors"].DefaultView;
MyDataGrid.DataBind();
MyDataGrid.DataSource=ds.Tables("Authors").DefaultView
MyDataGrid.DataBind()
MyDataGrid.DataSource=ds.Tables["Authors"].DefaultView;
MyDataGrid.DataBind();
|
| C# |
VB |
JScript |
|
替换语法是同时指定 DataSource 和 DataMember。这种情况下,ASP.NET 自动为您获取 DefaultView。
MyDataGrid.DataSource=ds;
MyDataGrid.DataMember="Authors";
MyDataGrid.DataBind();
MyDataGrid.DataSource=ds
MyDataGrid.DataMember="Authors"
MyDataGrid.DataBind()
MyDataGrid.DataSource=ds;
MyDataGrid.DataMember="Authors";
MyDataGrid.DataBind();
|
| C# |
VB |
JScript |
|
还可以直接绑定到 SqlDataReader。这种情况下只是显示数据,因此 SqlDataReader 的仅向前特性非常适合此方案,而您则从 SqlDataReader 提供的性能提升获益。
注意: 本节的其余部分只显示了数据访问的 DataSet 模型;不过,可以重写任何这些示例以便同样利用 SQLDataReader。
执行参数化选择
也可以使用 SqlDataAdapter 对象执行参数化选择。下面的示例显示可以如何修改使用从 select HtmlControl 传递的值所选择的数据。
SqlDataAdapter 维护一个可用于用值替换变量标识符(由名称前的"@"表示)的 Parameters 集合。在该集合中添加一个指定参数的名称、类型和大小的新 SqlParameter,然后将它的 Value 属性设置为选择的值。
myCommand.SelectCommand.Parameters.Add(new SqlParameter("@State", SqlDbType.NVarChar, 2));
myCommand.SelectCommand.Parameters["@State"].Value = MySelect.Value;
myCommand.SelectCommand.Parameters.Add(New SqlParameter("@State", SqlDbType.NVarChar, 2))
myCommand.SelectCommand.Parameters("@State").Value = MySelect.Value
myCommand.SelectCommand.Parameters.Add(new SqlParameter("@State", SqlDbType.NVarChar, 2));
myCommand.SelectCommand.Parameters("@State").Value = MySelect.Value;
|
| C# |
VB |
JScript |
|
重要说明: 注意 DataGrid 的 EnableViewState 属性已设置为 false。如果每个请求中都要填充数据,让 DataGrid 存储将通过往返行程由窗体发送来发送的状态信息没有好处。因为 DataGrid 在维护状态时存储其所有数据,适当时将其关闭很重要,这样可以提高页面性能。
DataGrid2.aspx 静态填充选择框的值,但这不太适合那些值在数据库中会更改的情况。因为 select HtmlControl 也支持 IEnumerable DataSource 属性,可以转而使用选择查询动态填充选择框,这将保证数据库和用户界面始终同步。下面的示例说明此过程。
在 SQL 数据库中插入数据
若要将行插入到数据库中,可以向页中添加简单的输入窗体,并在窗体提交事件处理程序中执行插入命令。与前两个示例一样,使用命令对象的 Parameters 集合填充命令的值。注意,在试图插入到数据库中之前,还要检查以确保所需的值非空。这将防止与数据库的字段约束意外冲突。还需在 try/catch 块的内部执行插入命令,以防插入行的主键已经存在。
不用显式检查输入值,而是可以轻松地使用 ASP.NET 提供的验证控件。下面的示例说明具体如何做。注意,使用 RegEx 验证程序提供了检查作者 ID、邮政编码和电话号码字段格式的额外好处。
更新 SQL 数据库中的数据
更新数据库在 Web 应用程序中可能经常很棘手。针对这种情况,DataGrid 控件提供了一些使更新更容易的内置支持。为了允许对行进行编辑,DataGrid 支持整型 EditItemIndex 属性,该属性指示网格的哪一行应该是可编辑的。设置了该属性后,DataGrid 按该索引将行呈现为文本输入框,而不是简单的标签。值 -1(默认值)指示没有行是可编辑的。页可以在服务器端窗体中包含 DataGrid,并通过 DataGrid 的对象模型获取对编辑数据的访问。
为了确定哪一行应该是可编辑的,需要一种方法接受用户关于他们希望编辑哪一行的输入。DataGrid 可以包含一个 EditCommandColumn 来呈现激发三个特殊事件的链接:EditCommand、UpdateCommand 和 CancelCommand。EditCommandColumn 以声明方式添加到 DataGrid 的 Columns 集合,如下面的示例所示。
<ASP:DataGrid id="MyDataGrid" runat="server"
...
OnEditCommand="MyDataGrid_Edit"
OnCancelCommand="MyDataGrid_Cancel"
OnUpdateCommand="MyDataGrid_Update"
DataKeyField="au_id"
>
<Columns>
<asp:EditCommandColumn EditText="Edit" CancelText="Cancel" UpdateText="Update" />
</Columns>
</ASP:DataGrid>
在 DataGrid 标记本身上,将事件处理程序连到从 EditCommandColumn 激发的每个命令。这些处理程序的 DataGridCommandEventArgs 参数使您得以直接访问由用来设置 DataGrid 的 EditItemIndex 的客户端选择的索引。注意,需要重新绑定 DataGrid 以使更改生效,如下面的示例所示。
public void MyDataGrid_Edit(Object sender, DataGridCommandEventArgs E) {
MyDataGrid.EditItemIndex = (int)E.Item.ItemIndex;
BindGrid();
}
Public Sub MyDataGrid_Edit(sender As Object, E As DataGridCommandEventArgs)
MyDataGrid.EditItemIndex = E.Item.ItemIndex
BindGrid()
End Sub
public function MyDataGrid_Edit(sender:Object, E:DataGridCommandEventArgs) : void {
MyDataGrid.EditItemIndex = int(E.Item.ItemIndex);
BindGrid();
}
|
| C# |
VB |
JScript |
|
当编辑某行 DataGrid 时,EditCommandColumn 呈现 Update 和 Cancel 链接。如果客户端选择 Cancel,只需将 EditItemIndex 设置回 -1。但如果客户端选择 Update,则需要对数据库执行更新命令。执行更新查询要求知道希望更新的行的数据库中的主键。为支持此要求,DataGrid 公开一个可以设置为主键字段名的 DataKeyField 属性。在连到 UpdateCommand 的事件处理程序中,可以从 DataGrid 的 DataKeys 集合检索键名。使用事件的 ItemIndex 在此集合中索引,如下面的示例所示。
myCommand.Parameters["@Id"].Value = MyDataGrid.DataKeys[(int)E.Item.ItemIndex];
myCommand.Parameters("@Id").Value = MyDataGrid.DataKeys(CType(E.Item.ItemIndex, Integer))
myCommand.Parameters["@Id"].Value = MyDataGrid.DataKeys[int(E.Item.ItemIndex)];
|
| C# |
VB |
JScript |
|
在 Update 事件处理程序的最后,将 EditItemIndex 设置回 -1。下面的示例说明此代码的运行。
前一示例的一个问题是,当行可编辑时,主键字段 (au_id) 也呈现为文本输入框。您不希望客户端更改该值,因为需要它来确定更新数据库中的哪一行。幸运的是,可以通过精确指定每一列相对于可编辑行的外观,禁用将此列呈现为文本框。为此需在 DataGrid 的 Columns 集合中定义每一行,使用 BoundColumn 控件分配每一列的数据字段。使用此方法,您可以完全控制列的顺序,以及它们的 ReadOnly 属性。对于 au_id 列,将 ReadOnly 属性设置为 true。当行处于编辑模式时,此列将继续呈现为标签。下面的示例说明此方法。
BoundColumn 控件不是唯一可以在 DataGrid 的 Columns 集合中设置的控件。还可以指定 TemplateColumn,它使您可以完全控制列的内容。模板的内容可以是任意的;在 DataGrid 的列中可以呈现任何内容,包括服务器控件。下面的示例说明如何使用 TemplateColumn 控件将“State”列呈现为下拉列表并将“Contract”列呈现为复选框 HtmlControl。ASP.NET 数据绑定语法用于输出模板中的数据字段值。注意,有一些棘手的逻辑使下拉列表和复选框反射行中的数据状态。
正如可以将下拉列表或复选框 HtmlControl 放置在 TemplateColumn 中,也可以将其他控件放置在那里。下面的示例在尝试执行更新前,将 Validator 控件添加到列以检查客户端输入。
删除 SQL 数据库中的数据
从数据库删除非常类似于更新或插入命令,但仍然需要一种方法来确定要具体删除的网格中的行。可以添加到 DataGrid 的 Columns 集合的另一个控件是 ButtonColumn 控件,它只呈现按钮控件。ButtonColumn 支持可以设置为 Delete 的 CommandName 属性。在 DataGrid 上,将事件处理程序连到 DeleteCommand,并从那里执行删除操作。再一次使用 DataKeys 集合确定客户端选择的行。下面的示例说明此过程。
将 SQL 数据库中的数据排序
对任何网格的共同要求是能够将它包含的数据排序。虽然 DataGrid 控件不为您显式排序它的数据,但它确实提供一种方法,在用户单击可用来排序数据的列标头时调用事件处理程序。当 DataGrid 的 AllowSorting 属性设置为 true 时,它呈现将 Sort 命令激发回网格的列标头的超级链接。将 DataGrid 的 OnSortCommand 属性设置为当用户单击列链接时要调用的处理程序。列的名称作为 DataGridSortCommandEventArgs 参数上的 SortExpression 属性传递,该参数可用来设置绑定到网格的 DataView 的 Sort 属性。下面的示例说明此过程。
<script>
protected void MyDataGrid_Sort(Object Src, DataGridSortCommandEventArgs E) {
...
DataView Source = ds.Tables["Authors"].DefaultView;
Source.Sort = E.SortExpression;
MyDataGrid.DataBind();
}
</script>
<form runat="server">
<ASP:DataGrid id="MyDataGrid" OnSortCommand="MyDataGrid_Sort" AllowSorting="true" runat="server" />
</form>
<script>
Protected Sub MyDataGrid_Sort(Src As Object, E As DataGridSortCommandEventArgs)
...
DataView Source = ds.Tables("Authors").DefaultView
Source.Sort = E.SortExpression
MyDataGrid.DataBind()
End Sub
</script>
<form runat="server">
<ASP:DataGrid id="MyDataGrid" OnSortCommand="MyDataGrid_Sort" AllowSorting="true" runat="server" />
</form>
<script>
protected function MyDataGrid_Sort(Src:Object, E:DataGridSortCommandEventArgs) : void {
...
var Source:DataView = ds.Tables["Authors"].DefaultView;
Source.Sort = E.SortExpression;
MyDataGrid.DataBind();
}
</script>
<form runat="server">
<ASP:DataGrid id="MyDataGrid" OnSortCommand="MyDataGrid_Sort" AllowSorting="true" runat="server" />
</form>
|
| C# |
VB |
JScript |
|
下面的示例显示此代码的运行。
当使用 BoundColumn 控件时,可以为每一列显式设置 SortExpression 属性,如下面的示例中的说明。
处理主-从关系
数据模型经常包含仅用单个网格无法表示的关系。很常见的基于 Web 的界面应该允许选择一行数据将客户端定位到“详细信息”页,而该页显示有关所选行的详细信息。为了用 DataGrid 实现此目的,可以将 HyperLinkColumn 添加到 Columns 集合,该集合指定单击链接时客户端定位到的详细信息页。使用格式字符串语法替代作为 querystring 参数传递的此链接中的字段值。下面的示例说明此过程。
<ASP:DataGrid id="MyDataGrid" runat="server">
<Columns>
<asp:HyperLinkColumn
DataNavigateUrlField="au_id"
DataNavigateUrlFormatString="datagrid13_details.aspx?id={0}"
Text="Get Details"
/>
</Columns>
</ASP:DataGrid>
在详细信息页上,检索 querystring 参数并执行联接选择以从数据库获取详细信息。下面的示例说明此情形。
编写和使用存储过程
一般情况下,执行特殊查询是以牺牲性能为代价的。使用存储过程可以减少在应用程序中执行繁重的数据库操作的开销。存储过程易于创建,甚至可以通过 SQL 语句来实现。以下代码示例创建一个只返回表的存储过程。
CREATE Procedure GetAuthors AS
SELECT * FROM Authors
return
GO
可以创建同样接受参数的存储过程。例如:
CREATE Procedure LoadPersonalizationSettings (@UserId varchar(50)) AS
SELECT * FROM Personalization WHERE UserID=@UserId
return
GO
从 ASP.NET 页使用存储过程只是您迄今为止已经学习的 SqlCommand 对象知识的扩展。CommandText 只是存储过程的名称,而不是特殊查询文本。通过设置 CommandType 属性,向 SqlCommand 指出 CommandText 是存储过程。
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure
myCommand.SelectCommand.CommandType = CommandType.StoredProcedure;
|
| C# |
VB |
JScript |
|
下面的示例说明如何调用存储过程以填充 DataSet。
将存储过程的参数作为特殊查询传递,如下面的示例所示。
访问基于 XML 的数据
在本节开始已经提到,DataSet 以独立于实际数据源的方式被设计为抽象数据。通过将示例的重点从 SQL 改为 XML,可以明白这一点。DataSet 支持将 FileStream 对象用作参数的 ReadXml 方法。在这种情况下读取的文件必须同时包含希望读取的架构和数据。DataSet 期望数据在窗体中,如下面的示例所示。
<DocumentElement>
<TableName>
<ColumnName1>column value</ColumnName1>
<ColumnName2>column value</ColumnName2>
<ColumnName3>column value</ColumnName3>
<ColumnName4>column value</ColumnName4>
</TableName>
<TableName>
<ColumnName1>column value</ColumnName1>
<ColumnName2>column value</ColumnName2>
<ColumnName3>column value</ColumnName3>
<ColumnName4>column value</ColumnName4>
</TableName>
</DocumentElement>
每个 TableName 节与表中的一行相对应。下面的示例显示如何使用 DataSet 的 ReadXml 方法从 XML 文件读取架构和数据。注意,数据读入 DataSet 后,它和 SQL 数据无法区分——DataGrid 同样绑定到它,如下面的示例所示。
也可以分别读取数据和架构,使用 DataSet 的 ReadXmlData 和 ReadXmlSchema 方法,如下面的示例所示。
正如 DataSet 对 XML 数据支持阅读器方法,它也支持写入数据。下面的示例实现从 SQL 选择数据并将结果写为 XML 数据或架构文本的工具。
- 公共语言运行库的托管数据访问 API 抽象数据并用一致的方式表示它,与实际的数据源(SQL Server、OLEDB、XML 等)无关。
- 为了使页能够访问执行 SQL 数据访问所需的类,必须将 System.Data 和 System.Data.SqlClient 命名空间导入到页中。
- 从 SQL 查询填充数据集涉及创建 SqlConnection、将 SqlDataAdapter 对象与包含查询语句的连接关联和从命令填充数据集。
- DataGrid 控件支持采用 IEnumerable(或 ICollection)类型的 DataSource 属性。通过分配 DataSet 的 DefaultView 属性(DataView 类型),可以将此设置为 SQL 查询的结果。
- SqlDataAdapter 维护一个可用于用值替换变量标识符(由名称前的“@”表示)的 Parameters 集合。
- 当执行不要求返回数据的命令(如插入、更新和删除)时,使用 SqlCommand,而不是 SqlDataAdapter。该命令通过调用 ExecuteNonQuery 方法发出,而该方法返回受影响的行数。
- 使用 SqlCommand 时必须显式打开 SqlConnection(SqlDataAdapter 自动地为您处理打开连接)。始终记住在页完成执行前关闭与数据模型的 SqlConnection。如果没有关闭连接,则可能会在等待页实例被垃圾收集回收时不经意超过连接限制。
- 为了允许对行进行编辑,DataGrid 支持整型 EditItemIndex 属性,该属性指示网格的哪一行应该是可编辑的。设置了该属性后,DataGrid 按该索引将行呈现为文本输入框,而不是简单的标签。
- DataGrid 公开一个可设置为主键字段名的 DataKeyField 属性。在连到 UpdateCommand 的事件处理程序中,可以从 DataGrid 的 DataKeys 集合检索键名。
- 使用 DataGrid 中的 BoundColumn 控件使您可以完全控制列的顺序,以及它们的 ReadOnly 属性。
- 使用 DataGrid 中的 TemplateColumn 控件使您可以完全控制列的内容。
- ButtonColumn 控件可用于在该列的每一行中仅呈现按钮控件,而该列可与事件关联。
- HyperLinkColumn 可以添加到 DataGrid 的 Columns 集合,该集合支持在单击链接时定位到另一页。
- 当 DataGrid 的 AllowSorting 属性设置为 true 时,它呈现将 Sort 命令激发回网格的列标头的超级链接。将 DataGrid 的 OnSortCommand 属性设置为当用户单击列链接时要调用的处理程序。
- DataSet 支持将 FileStream 作为参数的 ReadXml、ReadXmlData 和 ReadXmlSchema 方法,而该参数可用于从 XML 文件填充 DataSet。
- 使用存储过程可以减少在应用程序中执行繁重的数据库操作的开销。