Привязка данных 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 всего-лишь одним м-а-а-а-леньким атрибутом
Окончательный код страницы 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
-
Чтобы рассеять сомнения в том, что работает именно новый методзаключите (временно!) в файле UpdateEmployeeDB.cs исходный метод в комментарные скобки /*...*/public void UpdateEmployee(EmployeeDetails emp){...}/* // Исходный метод 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 | Редакция |




