ASP.NET - 使用 SqlDataSource 控件修改数据

时间:2021-12-17 07:30:34

 

      可以使用 SqlDataSource 控件修改数据库中的数据。使用更新方案中的 SqlDataSource 控件的最常用方法是检索数据并使用数据绑定 Web 服务器控件(如 GridViewDetailsView 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 控件有三个命令属性,即 InsertCommandUpdateCommand DeleteCommand 属性,这些属性可以包含用于修改数据的 SQL 语句。这些命令属性可以设置为 SQL 语句,或者,如果数据源支持存储过程,也可以设置为存储过程的名称。SQL 语句的实际语法取决于您的数据架构和您所使用的数据库。如果数据源支持参数,则语句中可以包含参数。

说明: 为命令属性设置的语句与在编写 ADO.NET 数据操作代码时为 ADO.NET IDbCommand 对象的 CommandText 属性设置的语句相同。

UpdateCommand 属性中的 SQL 语句在每次调用 Update 方法时执行。当用户在 GridViewFormView 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"/>

                        &nbsp;

                        <asp:LinkButton ID="NewButton"

                                        Text="New"

                                        CommandName="New"

                                        RunAt="server"/>

                        &nbsp;

                        <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"/>

                        &nbsp;

                        <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"/>

                        &nbsp;

                        <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 语句之前引发 InsertingUpdating Deleting 事件。可以为这些事件添加处理程序,从而在执行语句之前对其参数进行操作、重新排列或验证,还可以取消命令。例如,如果将 QueryStringParameter SqlDataSource 控件一起使用,则可以在执行更新之前处理 Updating 事件,以验证参数的值。(默认情况下,QueryStringParameter 采用查询字符串变量的值,并且不进行任何验证就将其提交至数据库。) 如果该值不可接受,则可以通过将事件的 SqlDataSourceCommandEventArgs 对象的 Cancel 属性设置为 true 来取消更新。

SqlDataSource 控件在数据库操作完成后引发 InsertedUpdated 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 事件以检查更新操作影响的记录数;如果未更新任何记录,则将发生并发冲突。