可以使用 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#" %>
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
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();
}
>
FormView Example
DataSourceID="EmployeesSqlDataSource" AutoGenerateColumns="false" DataKeyNames="EmployeeID" OnSelectedIndexChanged="EmployeesGridView_OnSelectedIndexChanged" RunAt="Server"> forecolor="White" /> HeaderText="Show CommandName="Select"/> DataSourceID="EmployeeDetailsSqlDataSource" DataKeyNames="EmployeeID" Gridlines="Both" OnItemUpdated="EmployeeFormView_ItemUpdated" OnItemDeleted="EmployeeFormView_ItemDeleted" RunAt="server"> forecolor="White"/> Text="Edit" CommandName="Edit" RunAt="server"/> Text="New" CommandName="New" RunAt="server"/> Text="Delete" CommandName="Delete" RunAt="server"/> Text='<%# Bind("FirstName") %>' RunAt="Server" /> Text='<%# Bind("LastName") %>' RunAt="Server" /> Text="Update" CommandName="Update" RunAt="server"/> Text="Cancel" CommandName="Cancel" RunAt="server"/> Text='<%# Bind("FirstName") %>' RunAt="Server" /> Text='<%# Bind("LastName") %>' RunAt="Server" /> Text="Insert" CommandName="Insert" RunAt="server"/> Text="Cancel" CommandName="Cancel" RunAt="server"/>
Details"
Employee ID: <%# Eval("EmployeeID") %> First Name: <%# Eval("FirstName") %> Last Name: <%# Eval("LastName") %>
Employee ID: <%# Eval("EmployeeID") %> First Name:
Last Name:
First Name:
Last Name:
selectCommand="SELECT EmployeeID, FirstName, LastName FROM Employees"
connectionstring="<%$ ConnectionStrings:NorthwindConnection %>"
RunAt="server">
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">
如果使用的数据库支持存储过程,则命令可以是存储过程的名称。如果使用存储过程更新数据,则必须将 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" %>
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.";
}
}
>
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">
id="DropDownList1"
runat="server"
DataTextField="LastName"
DataValueField="EmployeeID"
DataSourceID="SqlDataSource1">
AssociatedControlID="TextBox1" />
七、冲突检测
SqlDataSource 控件可以使用开放式并发执行更新和删除操作。开放式并发是一种数据库策略,可用于在多个用户同时操作数据时防止数据源中的更改丢失。SqlDataSource 控件使用 ConflictDetection 属性确定在执行更新和删除操作时要使用的开放式并发检查的级别。
默认情况下,ConflictDetection 属性被设置为 ConflictOptions.OverwriteChanges,表示更新操作将覆盖记录中的所有现有值,而不确定记录是否已被其他源修改。此方案有时称为“last writer wins”(最后的编写器成功)。
可以将 ConflictDetection 属性设置为 ConflictOptions.CompareAllValues,从而确保 SqlDataSource 控件在执行更新或删除命令期间包含所有的原始值。这样,您便可以采用这类方法编写 SQL 语句,以便在数据库中的当前数据与从数据库中最初读取的数据不匹配时,不执行更新操作。可以处理 Updated 事件以检查更新操作影响的记录数;如果未更新任何记录,则将发生并发冲突。