Изменение данных с помощью элемента управления SqlDataSource

Visual Studio 2010

Обновлен: Ноябрь 2007

Для изменения данных в базе данных можно использовать элемент управления SqlDataSource. Для использования элемента управления SqlDataSource в сценариях обновления как правило извлекают и отображают данные с помощью серверного веб-элемента управления с привязкой к данным, например, 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 используются три командных свойства, которые могут содержать инструкцию SQL для изменения данных. Это свойства InsertCommand, UpdateCommand и DeleteCommand. В качестве свойств команд можно задать инструкцию SQL или имя хранимой процедуры, если источник данных поддерживает хранимые процедуры. Фактический синтаксис инструкции SQL зависит схемы данных и используемой базы данных. Инструкция может содержать параметры, если источник данных поддерживает их.

fkzs2t3h.alert_note(ru-ru,VS.100).gifПримечание.

Инструкция, указанная в качестве значения свойства команды, является той же инструкцией, которая была указана для свойства CommandText объекта ADO.NET IDbCommand при создании кода обработки данных ADO.NET.

Инструкция SQL в свойстве UpdateCommand выполняется при каждом вызове метода Update. Метод Update вызывается неявным образом элементами управления с привязкой к данным при нажатии кнопки Обновить в элементе управления GridView,FormView или DetailsView. Можно также вызвать этот метод явно из собственного кода. Методы Insert и Delete элемента управления SqlDataSource используются аналогичным образом.

В следующем примере продемонстрировано использование элемента управления 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 xmlns="http://www.w3.org/1999/xhtml" >
  <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 для указания порядка параметров, типа параметров и направления параметров, а также дополнительных параметров, отличных от параметров, основанных на полях, привязанных к элементу управления. В качестве примера можно привести выходной параметр, возвращающий автоматически созданное источником данных значение, например, первичный ключ с автоматическим приращением или штамп даты и времени.

fkzs2t3h.alert_note(ru-ru,VS.100).gifПримечание.

Явное указание параметров особенно важно при работе с поставщиками System.Data.OleDb и System.Data.Odbc, которые не поддерживают именованные параметры в инструкциях SQL и используют местозаполнитель '?' для указания параметра. В этих случаях необходимо определить параметры в порядке, указанном в соответствующей инструкции SQL.

Дополнительные сведения и примеры использования параметров см. в разделах Использование параметров с элементом управления SqlDataSource и Создание параметров для полей, привязанных к данным, элементом управления источником данных.

Элемент управления SqlDataSource вызывает события, которые можно обработать для запуска своего собственного кода до или после выполнения элементом управления операций вставки, обновления или удаления.

Элемент управления SqlDataSource вызывает события Inserting, Updating или Deleting перед выполнением инструкции SQL для соответствующего свойства команды. Можно добавить обработчик этих событий для обработки, изменения порядка или проверки параметров инструкции, перед ее выполнением, а также для отмены команды. Например, при использовании QueryStringParameter с элементом управления SqlDataSource можно обработать событие Updating для проверки значения параметра до выполнения обновления. (По умолчанию параметр QueryStringParameter принимает значение строковой переменной запроса и передает его в базу данных, не выполняя каких-либо проверок). Если это значение неприемлемо, то можно отменить обновление, присвоив свойству Cancel события объекта SqlDataSourceCommandEventArgs значение 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 xmlns="http://www.w3.org/1999/xhtml" >
  <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>


<%@Page  Language="VJ#" %>
<%@Import Namespace="System.Data" %>
<%@Import Namespace="System.Data.Common" %>
<%@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, System.EventArgs e)
    {
        try {
            SqlDataSource1.Update();
        }
        catch (System.Exception except) {
            // Handle Exception
        }

        Label2.set_Text("The record was updated successfully!");
    } //On_Click

    private void OnSqlUpdate(Object source, SqlDataSourceCommandEventArgs e)
    {
        // Log the command in the Event Log on the Web server.
        String logInfo = e.get_Command().get_CommandText() 
            + " is being submitted to the database.";

        IEnumerator ie = e.get_Command().get_Parameters().GetEnumerator();
        while (ie.MoveNext()) {
            DbParameter param = ((DbParameter)(ie.get_Current()));
            logInfo = logInfo + " " + param.get_ParameterName()+ "=" 
            + param.get_Value();
        }

        EventLog log = new EventLog();
        log.set_Log("Application");
        log.set_Source("ASP.NET Example");
        log.WriteEntry(logInfo);
    } //OnSqlUpdate    

</script>

<html xmlns="http://www.w3.org/1999/xhtml" >
  <head runat="server">
    <title>ASP.NET Example</title>
</head>
<body>
    <form id="form1" runat="server">
      <asp:SqlDataSource
          id="SqlDataSource1"
          runat="server"
          ConnectionString="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;"
          SelectCommand="SELECT EmployeeID, LastName, Address FROM Employees"
          UpdateCommand="UPDATE Employees SET Address=@Address WHERE EmployeeID=@EmployeeID"
          OnUpdating="OnSqlUpdate">
          <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, что означает, что при выполнении операции обновления все существующие значения в записи перезаписываются, при этом не выполняется проверка того, была ли запись изменена другим источником. Этот сценарий иногда называют «кто последний, тот и прав».

Можно присвоить свойству ConflictDetection значение ConflictOptions.CompareAllValues, чтобы гарантировать, что элемент управления SqlDataSource содержит все исходные значения во время команды обновления или удаления. Это позволяет создать инструкцию SQL таким образом, что если данные, находящиеся в данный момент в базе данных, не соответствуют данным, которые были изначально считаны из базы данных, то операция обновления не выполняется. Пример см. в разделе Оптимистичный параллелизм (ADO.NET). Можно обработать событие Updated, чтобы проверить число записей; измененных при выполнении обновления. Отсутствие обновленных записей означает нарушение правила одновременного доступа.

Показ: