Опубликован: 07.05.2010 | Доступ: свободный | Студентов: 1678 / 62 | Оценка: 4.56 / 4.06 | Длительность: 34:11:00
Лекция 13:

Привязка данных ADO.NET

Применение перегруженного метода UpdateEmployee()

Исходный вариант метода UpdateEmployee() имеет четыре аргумента, которые автоматически используются как параметры канала передачи данных от источника отображения к полям таблицы. Но для тех же целей можно использовать любой промежуточный объект, описание (читай - класс, тип ) которого будет удовлетворять следующим условиям:

  • Если имеется параметризованный конструктор, то и обязательно должен быть объявлен конструктор по умолчанию, даже пустой (это стандартное требование языков C++ и C#)
  • Класс должен иметь общедоступные ( public ) и записываемые (не readonly ) свойства с именами, совпадающими с полями таблицы, для передачи данных в которую он будет использоваться

Таким условиям удовлетворяет вспомогательный класс EmployeeDetails, который мы разработали ранее и который имеет следующее описание в файле App_Code/EmployeeDetails.cs

using System;
    
public class EmployeeDetails
{
    // Общий конструктор
    public EmployeeDetails(int employeeID, string firstName, 
        string lastName, string titleOfCourtesy)
    {
        this.employeeID = employeeID;
        this.firstName = firstName;
        this.lastName = lastName;
        this.titleOfCourtesy = titleOfCourtesy;
    }
    
    // Конструктор по умолчанию обязателен, 
    // если создали общий конструктор
    public EmployeeDetails()
    {
    }
    
    // Добавляем свойства класса
    private int employeeID;
    public int EmployeeID
    {
        get { return employeeID; }
        set { employeeID = value; }
    }
    private string firstName;
    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; }
    }
    private string lastName;
    public string LastName
    {
        get { return lastName; }
        set { lastName = value; }
    }
    private string titleOfCourtesy;
    public string TitleOfCourtesy
    {
        get { return titleOfCourtesy; }
        set { titleOfCourtesy = value; }
    }
}

Объект класса EmployeeDetails вполне может служить каналом передачи данных из элемента GridView в таблицу при выполнении метода обновления, если его использовать в качестве аргумента этого метода. Дополним класс EmployeeDB еще одним перегружаемым методом UpdateEmployee().

  • Откройте на редактирование файл App_Code/UpdateEmployeeDB.cs и дополните его (скопируйте и чуть подправьте!) следующим кодом перегружаемого метода UpdateEmployee()
using System;
using System.Data;
    
using System.Data.SqlClient;
    
public partial class EmployeeDB
{
    // Исходный метод 
    public void UpdateEmployee(int employeeID, string firstName,
                               string lastName, string titleOfCourtesy)
    {
        SqlConnection con = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand("UpdateEmployee", con);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
        cmd.Parameters["@EmployeeID"].Value = employeeID;
        cmd.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10));
        cmd.Parameters["@FirstName"].Value = firstName;
        cmd.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20));
        cmd.Parameters["@LastName"].Value = lastName;
        cmd.Parameters.Add(new SqlParameter("@TitleOfCourtesy", SqlDbType.NVarChar, 25));
        cmd.Parameters["@TitleOfCourtesy"].Value = titleOfCourtesy;
    
        try
        {
            con.Open();
            cmd.ExecuteNonQuery();
        }
        catch
        {
            throw new ApplicationException("Ошибка данныx.");
        }
        finally
        {
            con.Close();
        }
    }
    
    // Перегружаемый метод с объектом класса EmployeeDetails
    public void UpdateEmployee(EmployeeDetails emp)
    {
        SqlConnection con = new SqlConnection(connectionString);
        SqlCommand cmd = new SqlCommand("UpdateEmployee", con);
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
        cmd.Parameters["@EmployeeID"].Value = emp.EmployeeID;
        cmd.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10));
        cmd.Parameters["@FirstName"].Value = emp.FirstName;
        cmd.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20));
        cmd.Parameters["@LastName"].Value = emp.LastName;
        cmd.Parameters.Add(new SqlParameter("@TitleOfCourtesy", SqlDbType.NVarChar, 25));
        cmd.Parameters["@TitleOfCourtesy"].Value = emp.TitleOfCourtesy;
    
        try
        {
            con.Open();
            cmd.ExecuteNonQuery();
        }
        catch
        {
            throw new ApplicationException("Ошибка данныx.");
        }
        finally
        {
            con.Close();
        }
    }
}

Теперь осталось создать страницу, реализующую этот новый канал обмена данными.

  • Сделайте копию страницы ObjectDataSourceUpdates1.aspx с именем ObjectDataSourceUpdates2.aspx и назначьте ее стартовой
  • Дополните описание объекта ObjectDataSource1 всего-лишь одним м-а-а-а-леньким атрибутом
    • DataObjectTypeName="EmployeeDetails" - для указания того, по описанию какого класса создавать промежуточный объект для передачи параметров в SQL-команду обновления данных в перегруженном методе UpdateEmployee()

Окончательный код страницы ObjectDataSourceUpdates2.aspx будет следующим

<%@ Page Language="C#" %>
    
<script runat="server">
    // Здесь мы не написали ни строчки кода!!!
</script>
    
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" 
            TypeName="EmployeeDB" 
            DataObjectTypeName="EmployeeDetails"            
            SelectMethod="GetAllEmployees" 
            UpdateMethod="UpdateEmployee" />
        <asp:GridView ID="GridView1" runat="server" 
            AutoGenerateColumns="False" 
            DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
                <asp:BoundField DataField="FirstName" HeaderText="Имя" />
                <asp:BoundField DataField="LastName" HeaderText="Фамилия" />
                <asp:BoundField DataField="TitleOfCourtesy" HeaderText="Статус" />
                <asp:CommandField ButtonType="Button" HeaderText="Изменить" 
                    ShowEditButton="True" ShowHeader="True"
                    EditText="Редакция" CancelText="Отмена" UpdateText="Применить" >
                    <HeaderStyle BackColor="Red" ForeColor="Yellow" />
                </asp:CommandField>
            </Columns>
        </asp:GridView>
    </div>
    </form>
</body>
</html>
  • Исполните страницу ObjectDataSourceUpdates2.aspx и убедитесь, что ее функциональность в точности повторяет функциональность страницы ObjectDataSourceUpdates1.aspx
  • Чтобы рассеять сомнения в том, что работает именно новый метод
    public void UpdateEmployee(EmployeeDetails emp){...}
    заключите (временно!) в файле UpdateEmployeeDB.cs исходный метод в комментарные скобки /*...*/
    /*		
     // Исходный метод 
     public void UpdateEmployee(int employeeID, string firstName,
                                string lastName, string titleOfCourtesy)
     {
      ...
     }
    */
  • Вновь запустите страницу ObjectDataSourceUpdates2.aspx. Функциональность полностью сохранилась, значит работает все-таки наш новый метод
  • Раскомментируйте исходный метод UpdateEmployee()

Применение иного метода обновления и нестандартных имен аргументов

К черту перегружаемые методы вместе с их стандартными именами аргументов, совпадающими с именами полей таблицы и порядком следования! Применим произвольные имена метода обновления и его аргументов (но количество аргументов оставим прежним, соответствующим количеству извлеченных в GridView полей).

Такая свобода требует написания дополнительного кода для подмены (в последний момент) в обработчике события ObjectDataSource.Updating значений в терминах GridView, в значения в терминах источника ObjectDataSource, передающего эти значения дальше в таблицу Employees для обновления конечных данных. Ранее мы подобную задачу решали на странице OtherNameParamUpdates.aspx применительно к элементу SqlDataSource.

  • Добавьте в класс EmployeeDB файла App_Code/UpdateEmployeeDB.cs копию исходного метода с четырьмя параметрами и подкорректируйте его так (теперь в файле будут три метода обновления)
    using System;
    using System.Data;
        
    using System.Data.SqlClient;
        
    public partial class EmployeeDB
    {
        // Исходный метод 
        public void UpdateEmployee(int employeeID, string firstName,
                                   string lastName, string titleOfCourtesy)
        {
         ...
        }
        
        // Перегружаемый метод с объектом класса EmployeeDetails
        public void UpdateEmployee(EmployeeDetails emp)
        {
         ...	
        }
        
        // Новый метод обновления данных
        // Изменены: имя метода, имена аргументов и порядок их следования
        public void UpdateEmployeeStrict(string titleOfCourtesyStrict, string lastNameStrict,
                                   string firstNameStrict, int employeeIDStrict)
        {
            SqlConnection con = new SqlConnection(connectionString);
            SqlCommand cmd = new SqlCommand("UpdateEmployee", con);
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
            cmd.Parameters["@EmployeeID"].Value = employeeIDStrict;
            cmd.Parameters.Add(new SqlParameter("@FirstName", SqlDbType.NVarChar, 10));
            cmd.Parameters["@FirstName"].Value = firstNameStrict;
            cmd.Parameters.Add(new SqlParameter("@LastName", SqlDbType.NVarChar, 20));
            cmd.Parameters["@LastName"].Value = lastNameStrict;
            cmd.Parameters.Add(new SqlParameter("@TitleOfCourtesy", SqlDbType.NVarChar, 25));
            cmd.Parameters["@TitleOfCourtesy"].Value = titleOfCourtesyStrict;
        
            try
            {
                con.Open();
                cmd.ExecuteNonQuery();
            }
            catch
            {
                throw new ApplicationException("Ошибка данныx.");
            }
            finally
            {
                con.Close();
            }
        }
    }
  • Сделайте копию страницы ObjectDataSourceUpdates1.aspx с именем ObjectDataSourceUpdates3.aspx и назначьте ее стартовой

Сейчас мы воспользуемся мощью оболочки Visual Studio 2005 и одним махом сгенерируем нужный нам код разметочной части страницы

  • Безжалостно (!!!) удалите в режиме Design настроенный (как-то там) объект ObjectDataSource1 и на его место из вкладки Data панели Toolbox скопируйте новый объект типа ObjectDataSource с прежним именем
  • Щелкните мышью на треугольнике в правом верхнем углу объекта ObjectDataSource1, чтобы вызвать для него внутреннюю панель настройки

  • Щелкните на единственной, пока, ссылке Configure Data Source (сконфигурировать источник данных), чтобы запустить мастер генерации настроек элемента ObjectDataSource1
  • На первой странице мастера из раскрывающегося списка выберите используемый класс EmployeeDB и перейдите к следующей странице мастера конфигурации
  • На новой странице вначале установите вкладку SELECT, через которую установите метод GetAllEmployees() для заполнения элемента GridView1
  • Установите вкладку UPDATE, через которую установите наш новый метод обновления данных UpdateEmployeeStrict()

После щелчка на кнопке Finish, поскольку на странице уже имеется элемент GridView1, не согласованный с новыми настройками источника данных, мастер выдаст предупреждение с предложением автоматически привести их в соответствие (мы занимаемся декларативной стыковкой элементов под неусыпным присмотром среды проектирования - оболочки!)

  • Ответьте отрицательно - нам не нужны новые замены в настройках GridView1

Вот какой код сгенерировал мастер настроек объекта ObjectDataSource1 (Ах, какой умный Большой Билл! Даже уточнения типов параметров сгенерировал сам)

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    TypeName="EmployeeDB"
    SelectMethod="CountEmployees" 
    UpdateMethod="UpdateEmployeeStrict">
    <UpdateParameters>
        <asp:Parameter Name="titleOfCourtesyStrict" Type="String" />
        <asp:Parameter Name="lastNameStrict" Type="String" />
        <asp:Parameter Name="firstNameStrict" Type="String" />
        <asp:Parameter Name="employeeIDStrict" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Теперь осталось написать код подмены значений параметров из GridView1 в принимающих параметрах источника ObjectDataSource1 перед обновлением конечных данных

  • Выделите в режиме Design объект ObjectDataSource1 и через панель Properties двойным щелчком на поле события Updating создайте для него заготовку обработчика
  • Заполните обработчик так, чтобы окончательный код страницы стал следующим
<%@ Page Language="C#" %>
    
<script runat="server">
    
    protected void ObjectDataSource1_Updating(object sender, ObjectDataSourceMethodEventArgs e)
    {
        // Перегрузить данные на других лошадей для
        // продолжения поездки к базе данных
        e.InputParameters["firstNameStrict"] = e.InputParameters["FirstName"];
        e.InputParameters["lastNameStrict"] = e.InputParameters["LastName"];
        e.InputParameters["titleOfCourtesyStrict"] = e.InputParameters["TitleOfCourtesy"];
        e.InputParameters["employeeIDStrict"] = e.InputParameters["EmployeeID"];
    
        // Удалить из коллекции параметров ненужное
        e.InputParameters.Remove("FirstName");
        e.InputParameters.Remove("LastName");
        e.InputParameters.Remove("TitleOfCourtesy");
        e.InputParameters.Remove("EmployeeID");
    }
</script>
    
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>Untitled Page</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
            TypeName="EmployeeDB"
            SelectMethod="GetAllEmployees" 
            UpdateMethod="UpdateEmployeeStrict" 
            OnUpdating="ObjectDataSource1_Updating">
                
            <UpdateParameters>
                <asp:Parameter Name="titleOfCourtesyStrict" Type="String" />
                <asp:Parameter Name="lastNameStrict" Type="String" />
                <asp:Parameter Name="firstNameStrict" Type="String" />
                <asp:Parameter Name="employeeIDStrict" Type="Int32" />
            </UpdateParameters>
                
        </asp:ObjectDataSource>
            
                
        <asp:GridView ID="GridView1" runat="server" 
            AutoGenerateColumns="False" 
            DataSourceID="ObjectDataSource1">
                
            <Columns>
                <asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
                <asp:BoundField DataField="FirstName" HeaderText="Имя" />
                <asp:BoundField DataField="LastName" HeaderText="Фамилия" />
                <asp:BoundField DataField="TitleOfCourtesy" HeaderText="Статус" />
                <asp:CommandField ButtonType="Link" CancelText="Отмена" 
                    EditText="Редакция" HeaderText="Изменить"
                    ShowEditButton="True" ShowHeader="True" UpdateText="Применить">
                    <HeaderStyle BackColor="Red" ForeColor="Yellow" />
                </asp:CommandField>
            </Columns>
                
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Обратите внимание на выделенные места кода страницы, особенно на настройки управляющего столбца элемента GridView1 - в нем мы для разнообразия сменили интерфейс пользователя с кнопок на гиперссылки.

  • Запустите на выполнение ObjectDataSourceUpdates3.aspx и получите работающую страницу редактирования данных, стерилизованный (ссылки отключены) вариант HTML-вывода которой приведен ниже
№ п/п Имя Фамилия Статус Изменить
1 Nancy Davolio Ms. Редакция
2 Andrew Fuller Dr. Редакция
3 Janet Leverling Ms. Редакция
4 Margaret Peacock Mrs. Редакция
5 Steven Buchanan Mr. Редакция
6 Michael Suyama Mr. Редакция
7 Robert King Mr. Редакция
8 Laura Callahan Ms. Редакция
9 Владимир Снетков Доцент 007 Редакция