可以使用 SqlDataSource 控件修改数据库中的数据。使用更新方案中的 SqlDataSource 控件的最常用方法是检索数据并使用数据绑定 Web 服务器控件(如 GridView、DetailsView 或 FormView 控件)显示数据。可以配置数据绑定控件和 SqlDataSource 以更新数据。大多数数据绑定控件都允许您将其配置为支持插入、更新及删除操作,并且它们会将要更新的值传递给数据源控件。然后,数据源控件会使用 SQL 语句或存储过程将更新后的值提交到数据库。
SqlDataSource 控件被设计为以一次更新一个记录的方式更新数据。如果需要执行批处理更新,则必须在 ASP.NET 应用程序中编写显式循环逻辑。
一、基本操作
若要使用 SqlDataSource 控件修改数据库中的数据,需要至少设置以下属性:
·ProviderName: 设置为 ADO.NET 提供程序的名称,该提供程序表示您正在使用的数据库。
·ConnectionString: 设置为用于数据库的连接字符串。
·SqlDataSource 命令属性: 设置为修改数据库中的数据的 SQL 语句。
二、提供程序名称
将 ProviderName 属性设置为存储数据的数据库类型的 ADO.NET 提供程序名称,该操作可以包括以下内容:
·如果您正在使用 Microsoft SQL Server,请将 ProviderName 属性设置为“System.Data.SqlClient”。如果您没有指定其他提供程序,则该提供程序将为默认提供程序。
·如果您正在使用 Oracle 数据库,请将 ProviderName 属性设置为“System.Data.OracleClient”。
·如果您正在使用 OLE DB 数据源,请将 ProviderName 属性设置为“System.Data.OleDb”。
·如果您正在使用 ODBC 数据源,请将 ProviderName 属性设置为“System.Data.Odbc”。
三、连接字符串
要连接至特定数据库,请设置 ConnectionString 属性。建议您将连接字符串存储在应用程序配置文件的 ConnectionStrings 元素中。然后,可以使用控件标记中的 <%$ ConnectionStrings:connectionStringName %> 语法引用存储的连接字符串。连接字符串必须为指定 ProviderName 的有效连接字符串。
四、命令
SqlDataSource 控件有三个命令属性,即 InsertCommand、UpdateCommand 和 DeleteCommand 属性,这些属性可以包含用于修改数据的 SQL 语句。这些命令属性可以设置为 SQL 语句,或者,如果数据源支持存储过程,也可以设置为存储过程的名称。SQL 语句的实际语法取决于您的数据架构和您所使用的数据库。如果数据源支持参数,则语句中可以包含参数。
说明: 为命令属性设置的语句与在编写 ADO.NET 数据操作代码时为 ADO.NET IDbCommand 对象的 CommandText 属性设置的语句相同。
UpdateCommand 属性中的 SQL 语句在每次调用 Update 方法时执行。当用户在 GridView、FormView 或 DetailsView 控件中单击“更新”按钮时,Update 方法将由数据绑定控件隐式调用。还可以通过自己的代码显式调用此方法。SqlDataSource 控件的 Insert 和 Delete 方法的工作方式类似。
下面的代码示例显示如何使用 SqlDataSource 控件插入、更新和删除使用 FormView 控件的记录。该示例连接至 SQL Server Northwind 数据库。
<%@ Page language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
void EmployeesGridView_OnSelectedIndexChanged(Object sender, EventArgs e)
{
EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
EmployeesGridView.SelectedValue.ToString();
EmployeeFormView.DataBind();
}
void EmployeeFormView_ItemUpdated(Object sender, FormViewUpdatedEventArgs e)
{
EmployeesGridView.DataBind();
}
void EmployeeFormView_ItemDeleted(Object sender, FormViewDeletedEventArgs e)
{
EmployeesGridView.DataBind();
}
void EmployeeDetailsSqlDataSource_OnInserted(Object sender, SqlDataSourceStatusEventArgs e)
{
System.Data.Common.DbCommand command = e.Command;
EmployeeDetailsSqlDataSource.SelectParameters["EmpID"].DefaultValue =
command.Parameters["@EmpID"].Value.ToString();
EmployeesGridView.DataBind();
EmployeeFormView.DataBind();
}
</script>
<html >
<head runat="server">
<title>FormView Example</title>
</head>
<body>
<form id="form1" runat="server">
<h3>FormView Example</h3>
<table cellspacing="10">
<tr>
<td>
<asp:GridView ID="EmployeesGridView"
DataSourceID="EmployeesSqlDataSource"
AutoGenerateColumns="false"
DataKeyNames="EmployeeID"
OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged"
RunAt="Server">
<HeaderStyle backcolor="Navy"
forecolor="White" />
<Columns>
<asp:ButtonField Text="Details..."
HeaderText="Show<BR>Details"
CommandName="Select"/>
<asp:BoundField DataField="EmployeeID" HeaderText="Employee ID"/>
<asp:BoundField DataField="LastName" HeaderText="Last Name"/>
<asp:BoundField DataField="FirstName" HeaderText="First Name"/>
</Columns>
</asp:GridView>
</td>
<td valign="top">
<asp:FormView ID="EmployeeFormView"
DataSourceID="EmployeeDetailsSqlDataSource"
DataKeyNames="EmployeeID"
Gridlines="Both"
OnItemUpdated="EmployeeFormView_ItemUpdated"
OnItemDeleted="EmployeeFormView_ItemDeleted"
RunAt="server">
<HeaderStyle backcolor="Navy"
forecolor="White"/>
<RowStyle backcolor="White"/>
<EditRowStyle backcolor="LightCyan"/>
<ItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID") %></td></tr>
<tr><td align="right"><b>First Name:</b></td> <td><%# Eval("FirstName") %></td></tr>
<tr><td align="right"><b>Last Name:</b></td> <td><%# Eval("LastName") %></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="EditButton"
Text="Edit"
CommandName="Edit"
RunAt="server"/>
<asp:LinkButton ID="NewButton"
Text="New"
CommandName="New"
RunAt="server"/>
<asp:LinkButton ID="DeleteButton"
Text="Delete"
CommandName="Delete"
RunAt="server"/>
</td>
</tr>
</table>
</ItemTemplate>
<EditItemTemplate>
<table>
<tr><td align="right"><b>Employee ID:</b></td><td><%# Eval("EmployeeID") %></td></tr>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="EditFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>
<tr><td align="right"><b>Last Name:</b></td>
<td><asp:TextBox ID="EditLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="UpdateButton"
Text="Update"
CommandName="Update"
RunAt="server"/>
<asp:LinkButton ID="CancelUpdateButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</EditItemTemplate>
<InsertItemTemplate>
<table>
<tr><td align="right"><b>First Name:</b></td>
<td><asp:TextBox ID="InsertFirstNameTextBox"
Text='<%# Bind("FirstName") %>'
RunAt="Server" /></td></tr>
<tr><td align="right"><b>Last Name:</b></td>
<td><asp:TextBox ID="InsertLastNameTextBox"
Text='<%# Bind("LastName") %>'
RunAt="Server" /></td></tr>
<tr>
<td colspan="2">
<asp:LinkButton ID="InsertButton"
Text="Insert"
CommandName="Insert"
RunAt="server"/>
<asp:LinkButton ID="CancelInsertButton"
Text="Cancel"
CommandName="Cancel"
RunAt="server"/>
</td>
</tr>
</table>
</InsertItemTemplate>
</asp:FormView>
</td>
</tr>
</table>
<asp:sqlDataSource ID="EmployeesSqlDataSource"
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
</asp:sqlDataSource>
<asp:sqlDataSource ID="EmployeeDetailsSqlDataSource"
SelectCommand="SELECT EmployeeID, LastName, FirstName FROM Employees WHERE EmployeeID = @EmpID"
InsertCommand="INSERT INTO Employees(LastName, FirstName) VALUES (@LastName, @FirstName);
SELECT @EmpID = SCOPE_IDENTITY()"
UpdateCommand="UPDATE Employees SET LastName=@LastName, FirstName=@FirstName
WHERE EmployeeID=@EmployeeID"
DeleteCommand="DELETE Employees WHERE EmployeeID=@EmployeeID"
ConnectionString="<%$ ConnectionStrings:NorthwindConnection %>"
OnInserted="EmployeeDetailsSqlDataSource_OnInserted"
RunAt="server">
<SelectParameters>
<asp:Parameter Name="EmpID" Type="Int32" DefaultValue="0" />
</SelectParameters>
<InsertParameters>
<asp:Parameter Name="EmpID" Direction="Output" Type="Int32" DefaultValue="0" />
</InsertParameters>
</asp:sqlDataSource>
</form>
</body>
</html>
如果使用的数据库支持存储过程,则命令可以是存储过程的名称。如果使用存储过程更新数据,则必须将 UpdateCommandType 属性设置为 StoredProcedure。
五、参数
参数用于向数据源发送插入、更新和删除操作的值。参数名和值基于绑定到控件的数据字段,或者基于显式定义的参数对象。数据绑定控件中的参数包括数据操作值和用于标识特定行的键值(由绑定控件的 DataKeyNames 属性定义)的值。
可以创建显式 Parameter 定义,以指定参数顺序、参数类型和参数方向,以及其他未基于绑定到控件的字段的参数。例如输出参数,该参数返回由数据源(如自动增量主键或日期时间戳)自动生成的值。
说明: 使用 System.Data.OleDb 和 System.Data.Odbc 提供程序(它们不支持 SQL 语句中的命名参数,而是使用“?”占位符指定参数)时,显式指定参数特别重要。在这些情况下,应该按照关联的 SQL 语句中指定的顺序定义参数。
六、事件
SqlDataSource 控件引发您可以处理的事件,以便在该控件执行插入、更新或删除操作前后运行您自己的代码。
SqlDataSource 控件在执行相应命令属性的 SQL 语句之前引发 Inserting、Updating 或 Deleting 事件。可以为这些事件添加处理程序,从而在执行语句之前对其参数进行操作、重新排列或验证,还可以取消命令。例如,如果将 QueryStringParameter 与 SqlDataSource 控件一起使用,则可以在执行更新之前处理 Updating 事件,以验证参数的值。(默认情况下,QueryStringParameter 采用查询字符串变量的值,并且不进行任何验证就将其提交至数据库。) 如果该值不可接受,则可以通过将事件的 SqlDataSourceCommandEventArgs 对象的 Cancel 属性设置为 true 来取消更新。
SqlDataSource 控件在数据库操作完成后引发 Inserted、Updated 或 Deleted 事件。您可以处理这些事件,以确定在数据库操作期间是否引发了异常,了解受操作影响的记录数,或检查数据库操作返回的任何输出值。
例如,下面的代码示例使用 Updating 和 Updated 事件在事务中执行 UpdateCommand。
<%@Page Language="C#" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.Common" %>
<%@Import Namespace="System.Data.SqlClient" %>
<%@Import Namespace="System.Diagnostics" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
private void On_Click(Object source, EventArgs e) {
SqlDataSource1.Update();
}
private void OnSqlUpdating(Object source, SqlDataSourceCommandEventArgs e) {
DbCommand command = e.Command;
DbConnection cx = command.Connection;
cx.Open();
DbTransaction tx = cx.BeginTransaction();
command.Transaction = tx;
}
private void OnSqlUpdated(Object source, SqlDataSourceStatusEventArgs e) {
DbCommand command = e.Command;
DbTransaction tx = command.Transaction;
// In this code example the OtherProcessSucceeded variable represents
// the outcome of some other process that occurs whenever the data is
// updated, and must succeed for the data change to be committed. For
// simplicity, we set this value to true.
bool OtherProcessSucceeded = true;
if (OtherProcessSucceeded) {
tx.Commit();
Label2.Text="The record was updated successfully!";
}
else {
tx.Rollback();
Label2.Text="The record was not updated.";
}
}
</script>
<html >
<head runat="server">
<title>ASP.NET Example</title>
</head>
<body>
<form id="form1" runat="server">
<asp:SqlDataSource
id="SqlDataSource1"
runat="server"
ConnectionString="<%$ ConnectionStrings:MyNorthwind%>"
SelectCommand="SELECT EmployeeID, LastName, Address FROM Employees"
UpdateCommand="UPDATE Employees SET Address=@Address WHERE EmployeeID=@EmployeeID"
OnUpdating="OnSqlUpdating"
OnUpdated ="OnSqlUpdated">
<UpdateParameters>
<asp:ControlParameter Name="Address" ControlId="TextBox1" PropertyName="Text"/>
<asp:ControlParameter Name="EmployeeID" ControlId="DropDownList1" PropertyName="SelectedValue"/>
</UpdateParameters>
</asp:SqlDataSource>
<asp:DropDownList
id="DropDownList1"
runat="server"
DataTextField="LastName"
DataValueField="EmployeeID"
DataSourceID="SqlDataSource1">
</asp:DropDownList>
<br />
<asp:Label id="Label1" runat="server" Text="Enter a new address for the selected user."
AssociatedControlID="TextBox1" />
<asp:TextBox id="TextBox1" runat="server" />
<asp:Button id="Submit" runat="server" Text="Submit" OnClick="On_Click" />
<br /><asp:Label id="Label2" runat="server" Text="" />
</form>
</body>
</html>
七、冲突检测
SqlDataSource 控件可以使用开放式并发执行更新和删除操作。开放式并发是一种数据库策略,可用于在多个用户同时操作数据时防止数据源中的更改丢失。SqlDataSource 控件使用 ConflictDetection 属性确定在执行更新和删除操作时要使用的开放式并发检查的级别。
默认情况下,ConflictDetection 属性被设置为 ConflictOptions.OverwriteChanges,表示更新操作将覆盖记录中的所有现有值,而不确定记录是否已被其他源修改。此方案有时称为“last writer wins”(最后的编写器成功)。
可以将 ConflictDetection 属性设置为 ConflictOptions.CompareAllValues,从而确保 SqlDataSource 控件在执行更新或删除命令期间包含所有的原始值。这样,您便可以采用这类方法编写 SQL 语句,以便在数据库中的当前数据与从数据库中最初读取的数据不匹配时,不执行更新操作。可以处理 Updated 事件以检查更新操作影响的记录数;如果未更新任何记录,则将发生并发冲突。