Программировать стараться - с конкурентами распрощаться
Профессиональное Web-приложение всегда имеет дело с данными, которые могут храниться в базе данных, XML- или структурированном файле, или где-то еще. Правильное отображение этих данных на странице пользователя так же важно, как и их извлечение. ADO.NET имеет механизм
Привязка одного значения позволяет связать свойство элемента управления с местом на странице. Это место называется вычислимым выражением привязки данных. Различают вычислимые # - выражения и более общие $ - выражения <.
Выражение
Выражение <%#...%> (в <? или <?=...?> ). Если выражение Page.DataBind() в сценарии страницы. Если мы забудем это сделать, то выражение
Пример корректных # - выражений
<%# Request .Browser .Browser %><%# GetUserName(ID) %><%# variable %><%# "Дорогой " + "друг " + name %><%# 2 * PI * radius + cos (alpha ) %>Пример интерфейсной части страницы, использующей несколько выражений
<html> <body> <form method="post" runat="server"> <asp:Image ID="Image1" runat="server" ImageUrl='<%# FilePath %>' /><br /> <asp:Label ID="Label1" runat="server" Text="<%# FilePath %>" /><br /> <asp:TextBox ID="TextBox1" runat="server" Text='<%# GetFilePath() %>' /><br /> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="<%# LogoPath.Value %>" Font-Bold="true" Text="Show logo" /><br /> <input type="hidden" ID="LogoPath" runat="server" value="MyMy.png"> <b><%# FilePath %></b><br /> <img src="<%# GetFilePath() %>"> </form> </body> </html>
В приведенном коде выражение DataBind() страницы.
Приведем простой пример.
Создайте новый сайт с именем WebSite9 командой File/New/Web Site (шаблон ASP.NET Web Site )
Скопируйте из проекта WebSite8 файл Web.Config, который должен иметь такой вид(рис ) Содержимое файла Web.Config<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="Northwind" connectionString=
"Data Source=localhost; Initial Catalog=Northwind; user id=sa; password=;" />
</connectionStrings>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Добавьте к приложению новую страницу с совмещенным кодом и именем SingleValueBinding.aspx, назначьте страницу стартовой
Вызовите для корня Web-дерева контекстное меню и создайте каталог Pictures сайта командой New Folder
Скопируйте из каталога Pictures данной работы в каталог Pictures сайта два файла: MyPhoto.jpg и MyMy.png (или любые другие рисунки)
Наполните страницу SingleValueBinding.aspx следующим кодом(рис ) Код страницы SingleValueBinding.aspx <%@ Page Language="C#" %>
<script runat="server">
// Объявления переменных класса
string cat = "Васька", photo;
// Методы
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
Label1.Text = "<h1>Заполните поля и пошлите запрос</h1>";
pict.Src = "Pictures/MyPhoto.jpg";
}
else
{
Label1.Text = "<h1>Вот Вам такие ответы</h1>";
photo = "Pictures/MyMy.png";
pict.Border = 3;
}
}
public int AddFun(string a, string b)
{
try
{
return Convert.ToInt32(a) + Convert.ToInt32(b);
}
catch
{
Label1.Text = "<h1 style='color:red'>В поля вводите целые числа</h1>";
Label1.Text += "<hr style='height:10; color:red' />";
return 0;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
this.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Выражения привязки одного значения</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="Label" />
<h2>
Кто сказал Мяу...?</h2>
<b style="color: Red">
<%# "Кот " + cat + "!" %>
</b>
<h2>
Сколько будет дважды-два?</h2>
<b style="color: Red">
<%# 2 * 2 %>
</b>
<h2>
Введите два <em>целых</em> числа<br />
и получите их сумму</h2>
<asp:TextBox ID="TextBox1" runat="server" />
+
<asp:TextBox ID="TextBox2" runat="server" />
= <b style="color: Red">
<%# AddFun(TextBox1.Text, TextBox2.Text) %></b>
<h2>Кто здесь изображен?</h2>
<img id="pict" runat="server" src="<%# photo %>" />
<br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Выполнить" />
</div>
</form>
</body>
</html>
При первой загрузке страницы в текстовую метку выводится начальный заголовок <h1> и установленное по умолчанию значение свойства src <. Все выражения DataBind() страницы. Он заставляет выполниться все выражения <.
Выполните страницу SingleValueBinding.aspx и убедитесь в работоспособности выражений Результат при начальной загрузке страницы:

Результат после обратной отсылки страницы:

Некоторые элементы управления библиотеки .NET Framework, служащие для отображения данных, позволяют привязать сразу несколько своих дочерних элементов к
<select>, включая HtmlSelect, ListBox и DropDownListCheckBoxList и RadioButtonList, генерирующие BulletedList, создающий нумерованный или Все они наследуют от System.Web.UI., который содержит свойства, необходимые для привязки множественного значения. Эти свойства приведены в таблице
| Свойство | Описание | |
|---|---|---|
|
Подключает ссылку на объект с данными (для загрузки методом DataBind() ), имеющими |
|
DataSourceID |
Присоединяется к уже загруженному объекту данных. Используется как . Оба свойства сразу применять нельзя |
|
DataTextField |
Содержит наименование поля (столбца) таблицы, значения которого будут отображаться списком | |
<select size="3" name="ListBox1" id="ListBox1">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
|
![]() |
|
DataValueField |
Содержит наименование поля (столбца) таблицы, значения которого будут загружены в список как атрибуты value, но пользователь их не увидит |
|
<select size="3" name="ListBox1" id="ListBox1">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
|
![]() |
|
В свою очередь, класс ListControl наследует метод DataBind() от класса System.Web.UI., иницирующий привязку.
Для примера привязки множественного значения спроектируем страницу, в которой в качестве объекта, имитирующего (System., имеющий шаблонный метод IDictionary<TKey, TValue>.Add(TKey, TValue).
Добавьте к приложению страницу с неразделяемым кодом и именем RepeatedValueBinding.aspx
Заполните интерфейсную часть страницы следующим кодом<%@ Page Language="C#" %>
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<select runat="server" id="Select1"
datatextfield="Key" datavaluefield="Value" size="3" />
<select runat="server" id="Select2"
datatextfield="Key" datavaluefield="Value" />
<asp:ListBox runat="server" ID="ListBox1"
DataTextField="Key" DataValueField="Value" Rows="3" />
<asp:DropDownList runat="server" ID="DropDownList1"
DataTextField="Key" DataValueField="Value" />
<asp:RadioButtonList runat="server" ID="RadioButtonList1"
DataTextField="Key" DataValueField="Value" />
<asp:CheckBoxList runat="server" ID="CheckBoxList1"
DataTextField="Key" DataValueField="Value" />
<br />
<asp:Button runat="server" ID="GetSelection" Text="Получить выделенное" />
<br />
<br />
<asp:Literal runat="server" ID="Result" EnableViewState="false" />
</div>
</form>
</body>
</html>
Объявления первых двух статических списков нужно набирать вручную, чтобы подсказчик кода допускал к их атрибутам. Элемент управления все-равно будет заполняться при каждой обратной отсылке и отображать значения свойств выбранных дочерних элементов. Поэтому, чтобы не таскать состояние этого элемента с сервера на
Переведите редактор страницы в режим Design и Page_Load(), который заполните такprotected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
// Создать источник данных (коллекцию) с тремя элементами
Hashtable ht = new Hashtable(3);
// Добавить в коллекцию элементы по схеме: Add(Key, Value)
ht.Add("Иванов", "Value1");
ht.Add("Петров", "Value2");
ht.Add("Сидоров", "Value3");
// Связать элементы управления с источником данных
Select1.DataSource = ht;
Select2.DataSource = ht;
ListBox1.DataSource = ht;
DropDownList1.DataSource = ht;
RadioButtonList1.DataSource = ht;
CheckBoxList1.DataSource = ht;
// Загрузить данные в элементы управления
this.DataBind();
}
}
можно представить таблицей из двух столбцов. Первый столбец считается Key, второй - Value.
Запустите страницу, чтобы проверить работу механизма привязки множественного значения к списковым элементам управленияТеперь реализуем функциональность, чтобы при щелчке на кнопке элемент собирал и отображал информацию о выделенных
Создайте обработчик для кнопки Button и заполните его следующим кодомprotected void GetSelection_Click(object sender, EventArgs e)
{
try
{
Result.Text += "<li>В Select1 выбрано: "
+ "(\""
+ Select1.Items[Select1.SelectedIndex].Text // Key
+ "\", \""
+ Select1.Value + "\")"; // Value
Result.Text += "<li>В Select2 выбрано: "
+ "(\""
+ Select2.Items[Select2.SelectedIndex].Text // Key
+ "\", \""
+ Select2.Value + "\")"; // Value
Result.Text += "<li>В ListBox1 выбрано: "
+ "(\""
+ ListBox1.SelectedItem.Text // Key
+ "\", \""
+ ListBox1.SelectedItem.Value + "\")"; // Value
Result.Text += "<li>В DropDownList1 выбрано: "
+ "(\""
+ DropDownList1.SelectedItem.Text // Key
+ "\", \""
+ DropDownList1.SelectedItem.Value + "\")"; // Value
Result.Text += "<li>В RadioButtonList1 выбрано: "
+ "(\""
+ RadioButtonList1.SelectedItem.Text // Key
+ "\", \""
+ RadioButtonList1.SelectedItem.Value + "\")";// Value
// Проверяем флажки
int checkedCount = 0;
string checkString = "";
foreach (ListItem check in CheckBoxList1.Items)
{
if (check.Selected)
{
checkString += "(\""
+ check.Text // Key
+ "\", \""
+ check.Value + "\"); "; // Value
checkedCount++; // Считем выделенные флажки
}
}
if (checkedCount == 0)
Result.Text += "<li>В CheckBoxList1 ничего не выбрано!";
else
Result.Text += "<li>В CheckBoxList1 выбрано: " + checkString;
}
catch
{
Result.Text = "<h1 style='color:Red'>Выберите в каждом элементе</h1>";
}
}
Разница в коде доступа к <select>.
Выполните полностью готовую страницу, демонстрирующую работу механизма привязки множественного значения к списковым элементам управления, чтобы получить следующий результат
Предыдущий пример использует в качестве , потому что он реализует интерфейс
System..
В качестве :
System.Collections .ArrayList Microsoft.VisualBasic.Collection System.Collections .Hashtable System.Collections .Generic .Dictionary <TKey, TValue>System.Data.DataViewУчитывая, что DataReader представляет данные также в виде таблицы с именованными столбцами, мы можем так сформулировать DataReader будут загружены два нужных нам столбца: один из которых можно считать Key, другой - Value. В элементе управления свойству DataTextField нужно присвоить имя поля, отображаемого в списке, а свойству DataValueField - имя поля, неотображаемого в списке.
Приведем пример. Пусть мы хотим заполнить окно списка ListBox полными именами всех сотрудников, хранящихся в таблице Employees учебной базы данных Northwind. Чтобы получить два столбца DataReader, один из которых будет вычисляемый, нужно сформулировать
SELECT EmployeeID, TitleOfCourtesy + ' ' + FirstName + ' ' + LastName AS FullName FROM Employees
Добавьте к проекту новую страницу DataReaderListBinding.aspx с разделяемым кодом и назначьте ее стартовой
Оформите и настройте интерфейсную часть страницы DataReaderListBinding.aspx так, чтобы она имела следующее дескрипторное представление(рис ) Дескрипторное представление интерфейсной части страницы DataReaderListBinding.aspx<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="DataReaderListBinding.aspx.cs"
Inherits="DataReaderListBinding" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" runat="server" DataTextField="FullName"
DataValueField="EmployeeID" SelectionMode="Multiple" Rows="10" />
<br />
<br />
<asp:Button ID="GetSelection" runat="server" Text="Получить выделенное"
OnClick="GetSelection_Click" />
<br />
<br />
<asp:Literal ID="Result" runat="server" EnableViewState="False" />
</div>
</form>
</body>
</html>
Заполните файл поддержки DataReaderListBinding.aspx.cs следующим кодом(рис ) Код файла поддержки DataReaderListBinding.aspx.csusing System;
using System.Data;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
public partial class DataReaderListBinding : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
// Создать объекты Command и Connection
string connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
string sql = "SELECT EmployeeID, "
+ "TitleOfCourtesy + ' ' + FirstName + ' ' + LastName "
+ "AS FullName FROM Employees";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sql, con);
try
{
// Открыть соединение и получить DataReader
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
// Привязать DataReader к списку и заполнить список
ListBox1.DataSource = reader;
ListBox1.DataBind();
reader.Close();
}
finally
{
// Закрыть соединение
con.Close();
}
}
}
protected void GetSelection_Click(object sender, EventArgs e)
{
Result.Text = "<b>Выделены сотрудники:</b>";
Result.Text += "<ol>";
foreach (ListItem item in ListBox1.Items)
if (item.Selected)
Result.Text +=
String.Format("<li> (\"{0}\", \"{1}\")</li>", item.Text, item.Value);
Result.Text += "</ol>";
}
}
Здесь мы заполнили список только при первом запросе страницы, расчитывая, что далее заполненный список будет сохраняться в состоянии вида. Если в элементе ListBox1 отключить сохранение состояния вида, установив EnableViewState="False", то при обратной отсылке список окажется пустым (попробуйте!).
Исполните страницу DataReaderListBinding.aspx для получения следующего результата
Выделены сотрудники:
Если для DropDownList, CheckListBox или RadioButtonList вместо ListBox, то достаточно изменить объявление элемента управления в интерфейсной части страницы. Остальная часть кода останется прежней.
Кроме списковых элементов управления, которые можно использовать для отображения множественных данных, существуют более специализированные элементы управления, спроектированные специально для этих целей. К ним относятся , и . Кроме того, механизм привязки имеют и такие элементы, как , и , хотя и служат несколько для других целей.
Здесь мы поговорим об элементе управления , возможных способах его настройки и привязки к нему разных имеет свойство и метод DataBind(). Типовое объявление элемента в интерфейсной части страницы выглядит так:
<asp:GridView ID="GridView1" runat="server" />
Рассмотрим пример, в котором данные DataReader будут привязываться не к списковому элементу управления, а к .
Создайте новую страницу GridViewDataBind.aspx с разделяемым кодом и назначьте ее стартовой
Поместите на страницу из вкладки Data панели Toolbox элемент управления GridView
Откройте на редактирование файл GridViewDataBind.aspx.cs и заполните его следующим кодом(рис ) Код файла GridViewDataBind.aspx.csusing System;
using System.Data;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
public partial class DataReaderListBinding : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Создать объекты Command и Connection
string connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
string sql = "SELECT EmployeeID, FirstName, LastName, "
+ "Title, City FROM Employees";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sql, con);
try
{
// Открыть соединение и получить DataReader
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
// Привязать DataReader к GridView
GridView1.DataSource = reader;
GridView1.DataBind();
reader.Close();
}
finally
{
// Закрыть соединение
con.Close();
}
}
}
Исполните страницу GridViewDataBind.aspx для получения следующего результат| EmployeeID | City | |||
|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma |
| 3 | Janet | Leverling | Sales Representative | Kirkland |
| 4 | Margaret | Peacock | Sales Representative | Redmond |
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 8 | Laura | Callahan | Redmond | |
| 9 | Dodsworth | Sales Representative | London |
В библиотеке .NET Framework имеется ряд классов, которые соединяются с любым поставщиком данных ADO.NET, облегчая IDataSource.

К
System.Web.UI.WebControls .ObjectDataSource - позволяет подключиться к пользовательскому классу доступа к даннымSystem.Web.UI.WebControls .SqlDataSource - позволяет подключиться к любому поставщику ADO.NETSystem.Web.UI.WebControls .SiteMapDataSource - позволяет подключиться к файлу System.Web.SiteMap, описывающему навигационную структуру Web-сайтаSystem.Web.UI.WebControls .XmlDataSource - позволяет подключиться к XML-файлуВсе эти классы представлены как элементы управления на вкладке Data панели Toolbox оболочки Visual Studio 2005 и являются новшеством библиотеки .NET Framework 2.0. Если перенести этот элемент на страницу, то он отображается серым цветом как невизуальный компонент страницы. В то же время в разметочной части страницы появляется соответствующий
System.Data.Common System.Data.SqlClientSystem.Data.OracleClientSystem.Data.OleDbSystem.Data.Odbc Чтобы манипулировать данными одной конкретной таблицы базы данных, требуется создать для нее свой
ConnectionStringProviderNameText или StoredProcedure ) в свойствах SelectCommandType, InsertCommandType, UpdateCommandType и DeleteCommandTypeSelectQuery, InsertQuery, UpdateQuery и DeleteQuery (Такие имена имеют свойства в панели Properties, которые в дескрипторном представлении SelectCommand, InsertCommand, UpdateCommand и DeleteCommand )Нам нужно определять команды только для тех типов действий, которые мы намерены выполнить. Так, например, если мы используем SelectQuery.
Приведем пример Employees учебной базы данных Northwind.
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />

Создав и настроив HtmlSelect, ListBox, DropDownList, CheckBoxList, RadioButtonList, BulletedList уже на Page_Load(). Более того, если выполнить команду Refresh Scheme встроенной панели Page.DataBind() в коде страницы для заполнения элементов отображения, не нужно - все будет выполняться автоматически при запуске страницы.
Создайте страницу с объединенным кодом и именем SqlDataSourceSimple.aspx. Назначьте ее стартовой
Из вкладки Data панели Toolbox добавьте на страницу неотображаемый элемент управления SqlDataSource , через который мы привяжем данные к элементу отображения
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления ListBox
Из вкладки Data панели Toolbox добавьте на страницу элемент управления GridView
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления Button
Настройте объекты страницы: SqlDataSource1, элемент отображения данных ListBox1, многофункциональный элемент отображения данных GridView1, кнопку обратной отсылки Button1 следующим образом(рис ) Разметочная часть страницы SqlDataSourceSimple.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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" /></div>
</form>
</body>
</html>
Исполните страницу SqlDataSourceSimple.aspx, чтобы получить следующий результат
| EmployeeID | City | |||
|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma |
| 3 | Janet | Leverling | Sales Representative | Kirkland |
| 4 | Margaret | Peacock | Sales Representative | Redmond |
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 8 | Laura | Callahan | Redmond | |
| 9 | Dodsworth | Sales Representative | London |

Все работает автоматически без необходимости написания кода (который нам тоже не страшен). на случай, если данные изменяются редко.
Если изменить свойство DataSourceMode (установлено по умолчанию) на DataReader и исполнить страницу, то в данном случае получим тот же самый результат. Режим DataSourceMode= работы DataSourceMode=DataReader, поскольку он поддерживает расширенную сортировку, фильтрацию и настройку . Однако, если стоит задача отображать большие экранные таблицы, то лучше использовать режим DataSourceMode=DataReader, потому что он более эффективно использует память сервера.
Применение
Приведем пример, в котором при выборе города в списковом элементе автоматически выбираются и отображаются в другом элементе все сотрудники, проживающие в данном городе. Мы будем использовать два элемента отображения, к каждому из которых привяжем по своему Employees
Создайте страницу с объединенным кодом и именем SqlDataSourceParameters.aspx. Назначьте ее стартовой
Удалите контейнер сценария <script runat="server">...</script > как ненужный для данного примера
Из вкладки Data панели Toolbox добавьте на страницу первый SqlDataSource , который будет поставлять список всех городов из таблицы Employees. Назовите его sourceEmployeeCities
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления DropDownList, который будет отображать все города, выбранные источником sourceEmployeeCities из таблицы Employees. Назовите его lstCities
Из вкладки Data панели Toolbox добавьте на страницу второй Employees, проживающих в переданном ему из раскрывающегося списка lstCities через параметр городе. Назовите его sourceEmployees
Из вкладки Data панели Toolbox добавьте на страницу элемент управления GridView с именем GridView1, который будет отображать список сотрудников, проживающих в выбранном городе и полученных из источника sourceEmployees
Настройте объекты страницы так, как показано ниже.При добавлении параметров пользуйтесь удобным редактором оболочки, позволяющим создавать команды и определять параметры. Редактор вызывается при выделенном элементе второго источника sourceEmployees щелчком на кнопке ( ...) свойства SelectQuery в панели Properties

Обратите внимание, что обратную отсылку мы выполняем за счет включенного свойства раскрывающегося списка lstCities. Обратите также внимание, что правильный перенос строковой константы в свойстве SelectCommand второго источника не влияет на возвращаемые SQL-командой результаты.
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT DISTINCT City FROM Employees" />
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True" DataSourceID="sourceEmployeeCities"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName,
Title, City FROM Employees WHERE City=@City">
<SelectParameters>
<asp:ControlParameter Name="City" ControlID="lstCities"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Исполните страницу SqlDataSourceParameters.aspx для получения следующего результатаВыберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 9 | Dodsworth | Sales Representative | London |
Здесь мы всю
Вернемся к редактору команд и параметров, представленному ранее окном

После набора команды в области SELECT щелчок на кнопке Refresh Parameters сканирует введенную команду и заполняет другие области и раскрывающиеся списки редактора нужной информацией, из которой можно потом быстро выбрать требуемое значение. В списке source перечислены типы элементов, которые могут передавать значения параметров в
Cookie ControlForm Profile QueryStringSession В нашем случае используется элемент управления DropDownList, поэтому мы установили тип параметра Control.
Предыдущий пример можно разбить на две страницы, чтобы продемонстрировать способ QueryString. На первой странице мы определим списковый элемент управления, который отобразит все города, находящиеся в таблице Employees учебной базы данных Northwind. На второй странице будем отображать список сотрудников, проживающих в выбранном городе. Информацию о городе будем перенаправлять в источник на второй странице через
Создайте новую страницу с объединенным кодом и именем QueryParameter1.aspx. Назначьте ее стартовой
Поместите на страницу SqlDataSource , списочный элемент ListBox и кнопку Button
Настройте свойства элементов так, как показано ниже, включая обработчики, полученные Page_Load ) и на кнопке ( cmdGo_Click )(рис ) Разметочная часть страницы QueryParameter1.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
lstCities.SelectedIndex = 0;
}
protected void cmdGo_Click(object sender, EventArgs e)
{
Response.Redirect("QueryParameter2.aspx?selectCity="
+ lstCities.SelectedValue);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница выбора города</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT DISTINCT City FROM Employees">
</asp:SqlDataSource>
<h2>
Выберите город</h2>
<asp:ListBox ID="lstCities" runat="server"
DataSourceID="sourceEmployeeCities"
DataTextField="City">
</asp:ListBox>
<br />
<br />
<asp:Button ID="cmdGo" runat="server" Text="Применить"
OnClick="cmdGo_Click" />
</div>
</form>
</body>
</html>
Создайте новую страницу с объединенным кодом и именем QueryParameter2.aspx
Поместите на страницу SqlDataSource и элемент GridView
Настройте свойства элементов так, как показано ниже(рис ) Разметочная часть страницы QueryParameter2.aspx<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница проживающих сотрудников</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName, Title,
City FROM Employees WHERE City=@City">
<SelectParameters>
<asp:QueryStringParameter Name="City" QueryStringField="selectCity" />
</SelectParameters>
</asp:SqlDataSource>
<h2>
Проживающие сотрудники</h2>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceEmployees" >
</asp:GridView>
</div>
</form>
</body>
</html>
Исполните страницу QueryParameter1.aspx и убедитесь, что запрос, сформированный на ней и направленный странице QueryParameter2.aspx на обработку, дает тот же самый результат, что и в предыдущем примереМы уже говорили о достоинствах
Прежде всего, создадим и запишем в базу данных
Скопируйте командой Add Existing Item из приложения WebSite8 разработанную нами ранее страницу SaveStoredProcedure.aspx и переименуйте ее в
Откройте на редактирование страницу SaveStoredProcedure1.aspx и откорректируйте ее так(рис ) Код страницы SaveStoredProcedure1.aspx для нового примера<%@ Page Language="C#" %>
<script runat="server">
// Объявления хранимых процедур
// Выборка городов
string sql1 =
"CREATE PROCEDURE GetCityes "
+ "AS "
+ "SELECT DISTINCT City FROM Employees";
// Выборка сотрудников для выбранного города
string sql2 =
"CREATE PROCEDURE GetEmployeesByCity "
+ "@paramCity varchar(15) "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, Title, City "
+ "FROM Employees WHERE City=@paramCity";
protected void Page_Load(object sender, EventArgs e)
{
// Извлекли строку соединения из web.config
string connectString = System.Web.Configuration.WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
// Создали объект соединения
System.Data.SqlClient.SqlConnection con =
new System.Data.SqlClient.SqlConnection(connectString);
// Создали объект Command
System.Data.SqlClient.SqlCommand cmd =
new System.Data.SqlClient.SqlCommand();
// Настроили объект Command
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.Text;
lblInfo.Text = "";
// Открываем соединение в безопасном режиме
try
{
con.Open();
}
catch
{
con.Close();
return;
}
// Выполняем команды в безопасном режиме
// Удаляем процедуры на случай повторного запуска этой страницы
try
{
cmd.CommandText = "DROP PROCEDURE GetCityes";
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"DROP PROCEDURE GetCityes\"<br />";
}
catch { }
try
{
cmd.CommandText = "DROP PROCEDURE GetEmployeesByCity";
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"DROP PROC GetEmployeesByCity\"<br />";
}
catch { }
// Выполняем команды в безопасном режиме
// Добавляем в базу данных хранимые процедуры
try
{
cmd.CommandText = sql1;
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"CREATE PROCEDURE GetCityes\"<br />";
}
catch { }
try
{
cmd.CommandText = sql2;
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"CREATE PROCEDURE GetEmployeesByCity\"<br />";
}
finally
{
con.Close();
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Label ID="lblInfo" runat="server" />
</form>
</body>
</html>
Исполните страницу SaveStoredProcedure1.aspx, чтобы добавить в базу данных Northwind две Теперь осталось воспользоваться этими
Скопируйте страницу SqlDataSourceParameters.aspx и присвойте ей имя StoredProcedureParam.aspx. Назначьте страницу StoredProcedureParam.aspx стартовой
Внесите в страницу StoredProcedureParam.aspx небольшие изменения, чтобы она стала такой(рис ) Код страницы StoredProcedureParam.aspx<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetCityes"
SelectCommandType="StoredProcedure">
</asp:SqlDataSource>
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True" DataSourceID="sourceEmployeeCities"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetEmployeesByCity"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="lstCities"
Name="paramCity" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Исполните страницу StoredProcedureParam.aspx и убедитесь, что она выдает точно такие же результаты, как и страница SqlDataSourceParameters.aspxВыберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 9 | Dodsworth | Sales Representative | London |
Теперь попробуем проверить работу
Выделите в панели Solution Explorer сразу две страницы QueryParameter1.aspx и QueryParameter2.aspx и создайте их копии с именами QueryStoredProcParam1.aspx и QueryStoredProcParam2.aspx. Назначьте страницу QueryStoredProcParam1.aspx стартовой
Заполните обе новых страницы следующими поправками(рис ) Код страницы QueryStoredProcParam1.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
lstCities.SelectedIndex = 0;
}
protected void cmdGo_Click(object sender, EventArgs e)
{
Response.Redirect("QueryStoredProcParam2.aspx?selectCity="
+ lstCities.SelectedValue);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница выбора города</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetCityes"
SelectCommandType="StoredProcedure">
</asp:SqlDataSource>
<h2>
Выберите город</h2>
<asp:ListBox ID="lstCities" runat="server"
DataSourceID="sourceEmployeeCities"
DataTextField="City">
</asp:ListBox>
<br />
<br />
<asp:Button ID="cmdGo" runat="server" Text="Применить"
OnClick="cmdGo_Click" />
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница проживающих сотрудников</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetEmployeesByCity"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:QueryStringParameter Name="paramCity" QueryStringField="selectCity" />
</SelectParameters>
</asp:SqlDataSource>
<h2>
Проживающие сотрудники</h2>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceEmployees" >
</asp:GridView>
</div>
</form>
</body>
</html>
Исполните страницу QueryStoredProcParam1.aspx и убедитесь, что получился тот же результат, что и в соответствующем примере без использования Любая среда исполнения программ при возникновении ошибки выдает соответствующее сообщение, которое для пользователя представляет набор непонятных символов. Задача прикладного программиста - предусмотреть в своем приложении перехват этого сообщения, распознавание его и замену на более понятные для пользователя рекомендации. Даже если код нашей страницы не содержит ошибок, все равно сбой может произойти по причинам, от нас не зависящим. Например, может быть не запущен во время запроса страницы
Сбой в работе сопровождается генерацией события, которое происходит сразу после возникновения ошибки. Сбой при выполнении запроса выбрасывает событие Selected, а при обновлении, вставке или удалении записей - события Updated, или Deleted соответственно. Мы можем предусмотреть обработку каждого из этих событий в отдельности или запланировать общий обработчик на любой из этих сбоев.
В обработчике ошибок можно получить доступ к объекту сгенерированного исключения через его свойство SqlDataSourceStatusEventArgs.Exception. Если после выброса исключения мы хотим подавить его далнейшее распространение, то в обработчике должны установить SqlDataSourceStatusEventArgs.ExceptionHandled в true.
В качестве примера предусмотрим общий обработчик возможных исключений на выполнение всех четырех операций выборки, обновления, вставки и
Создайте копию страницы SqlDataSourceSimple.aspx с именем SqlDataSourceException.aspx и назначьте ее стартовой
Откройте страницу SqlDataSourceException.aspx на редактирование в режиме Design и Page_Load()
В обработчике
Следуйте указаниям подсказчика кода и нажимайте клавишу
Указанным способом зарегистрируйте события (и создайте для каждого из них обработчики)SelectedUpdatedInserted DeletedПосле проведенных действий страница SqlDataSourceException.aspx должна выглядеть так
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Selected);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Updated);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Inserted);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Deleted);
}
void SqlDataSource1_Deleted(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Inserted(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Updated(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
</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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" /></div>
</form>
</body>
</html>
Оставьте только один обработчик, а остальные удалите
Измените имя оставшегося общего обработчика на SqlDataSource1_Error и внесите это имя в регистрацию каждого события, чтобы блок кода сценария стал таким<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
}
void SqlDataSource1_Error(object sender, SqlDataSourceStatusEventArgs e)
{
}
</script>
Теперь осталось обработать возможное исключение
Поместите в конец страницы текстовую метку Label с именем lblError
Заполните обработчик ошибки (рис ) Окончательный код страницы SqlDataSourceException.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
}
void SqlDataSource1_Error(object sender, SqlDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
// Известить пользователя, что команда не была завершена
lblError.Text = "<h1 style='color:#FF0000'>"
+ "При исполнении запроса произошло исключение!</h1>";
// Известить систему, что ошибка обработана
e.ExceptionHandled = true;
}
}
</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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" />
<asp:Label ID="lblError" runat="server" />
</div>
</form>
</body>
</html>
Чтобы испытать обработчик исключения, внесите какую-нибудь ошибку в 
Чтобы дать возможность пользователю редактировать записи в механизме множественной , и имеют такие средства, которые можно в них включить.
Настройка возможностей редактирования состоит из двух шагов:
UpdateQuery, InsertQuery и DeleteQueryКакие
Приведем пример, в котором дадим возможность пользователю редактировать таблицу Employees учебной базы данных Northwind.
Скопируйте страницу SqlDataSourceSimple.aspx с именем SqlDataSourceUpdates.aspx и назначьте ее стартовой
Удалите из нее объекты списка ListBox1 и кнопки Button1, чтобы остались только SqlDataSource1 и элемент отображения GridView1
Исполните страницу, чтобы убедиться, что данные, извлеченные источником из таблицы Employees, по-прежнему отображаются в GridView1Теперь настроим источник на обновление данных.
Выделите в режиме Design SqlDataSource1 и в панели Properties щелкните на кнопке с многоточием в поле UpdateQuery, чтобы запустить редактор формирования SQL-команды обновления записей с параметрами
Заполните поле UPDATE command редактора строкой SQL-команды с параметрамиUPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID
После щелчка на кнопке Refresh Parameters автоматически заполнится поле , как показано на рисунке

После таких действий редактор параметров сгенерирует дополнительные поправки в настройку
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID" >
<UpdateParameters>
<asp:Parameter Name="FirstName" />
<asp:Parameter Name="LastName" />
<asp:Parameter Name="Title" />
<asp:Parameter Name="City" />
<asp:Parameter Name="EmployeeID" />
</UpdateParameters>
</asp:SqlDataSource>
Обратите внимание, что имена параметров, предваряемых символом @, мы выбрали совпадающими с именами полей таблицы. Это необходимо потому, что объект GridView1 после привязки к нему
Исполните страницу SqlDataSourceUpdates.aspx с внесенными на данном этапе настройками Теперь осталось настроить интерфейсный объект GridView1 на возможность редактирования данных. Для этого добавим к GridView1 дополнительный столбец с функциями управления редактированием записей.
Вызовите внутреннюю панель настройки объекта GridView1, как показано на рисунке, и выберите пункт Edit Columns 
Появится диалоговое окно Fields, которое предоставляет в удобном виде настройки столбцов объекта GridView1

Используя диалоговое окно Fields выполните следующее:Auto -generate fields , чтобы отключить неконтролируемое отображение всех столбцовSelected fields пять столбцов типа BoundField, которые будут связаны с DataField (имя связываемого поля в HeaderText (отображаемый на экране заголовок столбца)CommandField/Edit, Update, Cancel и задайте ему следующие свойства:EditText="Редакция"CancelText="Отмена"UpdateText="ПрименитьButtonType="Button "HeaderText="Изменить"HeaderStyle/BackColor="Red"HeaderStyle/ForeColor="Yellow"В результате таких опосредованных действий оболочка сформирует следующее описание объекта GridView1
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Отчество" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" HeaderText="Проживает" />
<asp:CommandField ButtonType="Button" HeaderText="Изменить"
ShowEditButton="True" ShowHeader="True"
EditText="Редакция" CancelText="Отмена" UpdateText="Применить" >
<HeaderStyle BackColor="Red" ForeColor="Yellow" />
</asp:CommandField>
</Columns>
</asp:GridView>
В итоге окончательный код страницы будет следующим
<%@ 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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID" >
<UpdateParameters>
<asp:Parameter Name="FirstName" />
<asp:Parameter Name="LastName" />
<asp:Parameter Name="Title" />
<asp:Parameter Name="City" />
<asp:Parameter Name="EmployeeID" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" 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>
Запустите страницу и испытайте ее функциональность. Можно спокойно редактировать записи, не написав при этом ни строчки кода - все делает встроенный механизм ASP.NETСтраница SqlDataSourceUpdates.aspx в действии может выглядеть так
| № п/п | Имя | Фамилия | Статус | Проживает | Изменить |
|---|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond | |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma | |
| 3 | Janet | Leverling | Sales Representative | Kirkland | |
| 4 | Margaret | Peacock | Sales Representative | Redmond | |
| 5 | Steven | Buchanan | Sales Manager | London | |
| 6 | Michael | Suyama | Sales Representative | London | |
| 7 | Robert | King | Sales Representative | London | |
| 8 | Laura | Callahan | Redmond | ||
| 9 | Владимир | Снетков | Доцент 007 | Красноярск |
В добавленном столбце управления редактированием (его можно разместить на любом месте, изменив порядок следования для внесения изменений в базу данных.
Можно создать аналогичные InsertQuery и DeleteQuery. Чтобы разрешить, например, вставку в элементе отображения , нужно добавить управляющий столбец типа CommandField и установить его отображение в свойстве ShowInsertButton

В
Такая ситуация называется конкуренцией данных или конфликтом изменений. Для ее решения применяются разные способы, один из которых опирается на тот факт, что в элементе отображения хранятся как оригинальные значения полей, так и их последние изменения. Сам по умолчанию (например, @original_FirstName ), и измененными, носящими имя поля. Источник может понимать имена оригинальных параметров и с другим OldValuesParameterFormatString (например, xxx{0} ).
Принимая решение о сохранении конечных изменений в базе данных, мы можем сконфигурировать в
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@original_EmployeeID
AND FirstName=@original_FirstName
AND LastName=@original_LastName
AND Title=@original_Title AND City=@original_City"
Здесь для проверки неизменности полей в базе данных применяются оригинальные параметры, переданные из в
Подобную проверку ConflictDetection с OverwriteChanges (заменять без проверки, установлено по умолчанию) на CompareAllValues (заменять только при совпадении всех оригинальных значений).
Ранее мы говорили, что необходимым условием правильной пересылки данных из в с целью обновления конечных данных должно быть совпадение имен параметров с именами полей таблицы. Но иногда может возникнуть необходимость применить для обновления конечных данных чью-то подходящую
Рассмотрим этот способ на примере.
Скопируйте страницу SqlDataSourceUpdates.aspx с именем OtherNameParamUpdates.aspx и назначьте ее стартовой
Проверьте, что страница OtherNameParamUpdates.aspx работает
Назовите параметры источника другими именами, отличными от имен полей, например так(рис ) Назначение параметрам команды обновления других имен<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@paramFirstName,
LastName=@paramLastName, Title=@paramTitle, City=@paramCity
FROM Employees WHERE EmployeeID=@paramEmployeeID" >
<UpdateParameters>
<asp:Parameter Name="paramFirstName" Type="string" />
<asp:Parameter Name="paramLastName" Type="string" />
<asp:Parameter Name="paramTitle" Type="string" />
<asp:Parameter Name="paramCity" Type="string" />
<asp:Parameter Name="paramEmployeeID" Type="string" />
</UpdateParameters>
</asp:SqlDataSource>
Запустите страницу OtherNameParamUpdates.aspx и убедитесь, что конечные обновления в базе данных не выполняются из за того, что измененные поля не передаются из GridView1 в SqlDataSource1Для решения задачи используем событие , которое возбуждается непосредственно перед подтверждением обновлений.
Перейдите в режим Design редактирования страницы OtherNameParamUpdates.aspx и Page_Load()
Зайдите в тело обработчика и начинайте регистрировать событие Updating SqlDataSource1.Updating +=и далее используя клавишу
Оболочка создаст правильную заготовку обработчика события Updating. Теперь можно полностью удалить обработчик Page_Load() как неиспользуемый.
Удалите ненужный теперь обработчик Page_Load()
Добавьте к описанию источника атрибут OnUpdating="SqlDataSource1_Updating"Здесь мы пошли более длинным, но универсальным путем создания заготовки обработчика SqlDataSource1_Updating(). Знакомый нам более короткий и традиционный путь - создать заготовку обработчика через панель Properties, при этом имя обработчика автоматически добавится в описание
Заполните обработчик события Updating так, чтобы страница имела следующий вид(рис ) Окончательный код страницы OtherNameParamUpdates.aspx<%@ Page Language="C#" %>
<script runat="server">
void SqlDataSource1_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
// Передать значения нестандартным именам параметров
e.Command.Parameters["@paramFirstName"].Value =
e.Command.Parameters["@FirstName"].Value;
e.Command.Parameters["@paramLastName"].Value =
e.Command.Parameters["@LastName"].Value;
e.Command.Parameters["@paramTitle"].Value =
e.Command.Parameters["@Title"].Value;
e.Command.Parameters["@paramCity"].Value =
e.Command.Parameters["@City"].Value;
e.Command.Parameters["@paramEmployeeID"].Value =
e.Command.Parameters["@EmployeeID"].Value;
// Удалить из коллекции стандартные имена параметров
e.Command.Parameters.Remove(e.Command.Parameters["@FirstName"]);
e.Command.Parameters.Remove(e.Command.Parameters["@LastName"]);
e.Command.Parameters.Remove(e.Command.Parameters["@Title"]);
e.Command.Parameters.Remove(e.Command.Parameters["@City"]);
e.Command.Parameters.Remove(e.Command.Parameters["@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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@paramFirstName,
LastName=@paramLastName, Title=@paramTitle, City=@paramCity
FROM Employees WHERE EmployeeID=@paramEmployeeID"
OnUpdating="SqlDataSource1_Updating" >
<UpdateParameters>
<asp:Parameter Name="paramFirstName" Type="string" />
<asp:Parameter Name="paramLastName" Type="string" />
<asp:Parameter Name="paramTitle" Type="string" />
<asp:Parameter Name="paramCity" Type="string" />
<asp:Parameter Name="paramEmployeeID" Type="string" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" 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>
Запустите страницу OtherNameParamUpdates.aspx и убедитесь, что она сохранила прежние способности обновления данных в базеПереходим к следующей части...
Старательно сопишь - значит победишь
Компонент находится на вкладке Data панели Toolbox. Он позволяет создавать декларативным (на . Но для корректного применения пользовательский класс доступа к данным, которым может быть и разработанный нами класс, должен подчиняться нескольким правилам:
ObjectDataSource создает его экземпляры по необходимости и уничтожает их за собой в конце каждого запросаIEnumerable Выполнение этих правил гарантирует, что
Для дальнейшего рассмотрения применим
На корне Web-дерева создайте папку App_Code командой контекстного меню Add ASP.NET Folder
На папке Add_Code выполните команду Website/Add Existing Item и скопируйте из папки WebSite8/App_Code все ее содержимое, которое представляет собой описание пользовательского класса EmployeeDB
Вспомним, что ранее мы поместили в базу данных с помощью страницы WebSite8/SaveStoredProcedure.aspx
Скопируйте в текущее приложение страницу WebSite8/SaveStoredProcedure.aspx, откройте ее и посмотрите, что // Объявления хранимых процедур
// Вставка записи
string sql1 =
"CREATE PROCEDURE InsertEmployee "
+ "@EmployeeID int OUTPUT,"
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "INSERT INTO Employees "
+ "(TitleOfCourtesy, LastName, FirstName, HireDate) "
+ "VALUES(@TitleOfCourtesy, @LastName, @FirstName, GETDATE()) "
+ "SET @EmployeeID = @@IDENTITY";
// Удаление записи
string sql2 =
"CREATE PROCEDURE DeleteEmployee "
+ "@EmployeeID int "
+ "AS "
+ "DELETE FROM Employees WHERE EmployeeID = @EmployeeID";
// Обновление записи
string sql3 =
"CREATE PROCEDURE UpdateEmployee "
+ "@EmployeeID int, "
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "UPDATE Employees "
+ "SET "
+ "FirstName = @FirstName,"
+ "LastName = @LastName,"
+ "TitleOfCourtesy = @TitleOfCourtesy "
+ "WHERE EmployeeID = @EmployeeID";
// Выбрать все
string sql4 =
"CREATE PROCEDURE GetAllEmployees "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees";
// Подсчитать число записей
string sql5 =
"CREATE PROCEDURE CountEmployees "
+ "AS "
+ "SELECT COUNT(EmployeeID) "
+ "FROM Employees";
// Выбрать запись
string sql6 =
"CREATE PROCEDURE GetEmployee "
+ "@EmployeeID int "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees "
+ "WHERE EmployeeID = @EmployeeID";
В их числе и процедура GetAllEmployees, которую реализует в пользовательском классе EmployeeDB одноименный метод GetAllEmployees(). Эта процедура извлекает из таблицы Employees записи четырех полей в порядке их следования в имя нашего пользовательского класса и имя метода, который реализует в классе нужный сам создаст экземпляр этого пользовательского класса и вызовет указанный метод. В результате, объект пользовательского класса будет заполнен данными, которые увидит пользователь через привязанные к компоненту элементы отображения.
Создайте новую страницу с совмещенным кодом и именем ObjectDataSourceSimple.aspx. Назначьте ее стартовой
Перенесите на страницу ObjectDataSourceSimple.aspx из панели Toolbox следующие компонентыObjectDataSource из вкладки DataListBox из вкладки StandardGridView из вкладки Data
Выполните простые настройки свойств компонентов, чтобы окончательный код страницы стал таким(рис ) Код страницы ObjectDataSourceSimple.aspx после декларативных настроек <%@ Page Language="C#" %>
<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"
SelectMethod="GetAllEmployees"
TypeName="EmployeeDB" />
<asp:ListBox ID="ListBox1" runat="server"
DataSourceID="ObjectDataSource1" DataTextField="LastName" />
<asp:GridView ID="GridView1" runat="server"
DataSourceID="ObjectDataSource1" />
</div>
</form>
</body>
</html>
Исполните страницу ObjectDataSourceSimple.aspx, чтобы получить следующий результат
| TitleOfCourtesy | EmployeeID | ||
|---|---|---|---|
| Davolio | Ms. | 1 | Nancy |
| Fuller | Dr. | 2 | Andrew |
| Leverling | Ms. | 3 | Janet |
| Peacock | Mrs. | 4 | Margaret |
| Buchanan | Mr. | 5 | Steven |
| Suyama | Mr. | 6 | Michael |
| King | Mr. | 7 | Robert |
| Callahan | Ms. | 8 | Laura |
| Снетков | Доцент 007 | 9 | Владимир |
Исключительно простой получилась . Никакого кода не пришлось писать. Прямо - работа для дизайнеров или кухарок! Но пользовательский-то класс EmployeeDB мы ранее с вами создали. Его просто здесь не видно - он работает за кулисами и вызывается по ссылке, указанной в свойстве TypeName компонента . Элементы отображения, в свою очередь, получают свою порцию данных через ссылку на заполненный , указанную в свойстве DataSourceID.
Компонент сам создает экземпляр пользовательского класса и мы не имеем возможности декларативно передать в него информацию через параметры конструктора. Но можно воспользоваться событиями компонента , чтобы обойти это ограничение.
Компонент имеет богатую модель событий, представленную ниже
System.Web.UI.WebControls .ObjectDataSource .DeletedSystem.Web.UI.WebControls .ObjectDataSource .DeletingSystem.Web.UI.WebControls .ObjectDataSource .Filtering System.Web.UI.WebControls .ObjectDataSource .Inserted System.Web.UI.WebControls .ObjectDataSource .Inserting System.Web.UI.WebControls .ObjectDataSource .ObjectCreatedSystem.Web.UI.WebControls .ObjectDataSource .ObjectCreatingSystem.Web.UI.WebControls .ObjectDataSource .ObjectDisposingSystem.Web.UI.WebControls .ObjectDataSource .SelectedSystem.Web.UI.WebControls .ObjectDataSource .SelectingSystem.Web.UI.WebControls .ObjectDataSource .UpdatedSystem.Web.UI.WebControls .ObjectDataSource .UpdatingЭти события можно разделить на две категории:
ing - происходят во время выполнения задачи и позволяют вмешаться в этот процесс, что-то настроить или прерватьed - происходят по завершении задачи и удобны для Если мы хотим передать компоненту уже инициализированный параметризованным .
Продолжим эксплуатировать наш класс EmployeeDB, в котором как раз есть параметризованный
using System;
using System.Web.Configuration;
public partial class EmployeeDB
{
private string connectionString;
public EmployeeDB()
{
// Извлечь из файла web.config строку соединения по умолчанию
connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
}
public EmployeeDB(string connectionStringCustom)
{
// Извлечь из файла web.config другую строку соединения
connectionString = WebConfigurationManager.
ConnectionStrings[connectionStringCustom].ConnectionString;
}
}
Скопируйте страницу ObjectDataSourceSimple.aspx под именем ObjectDataSourceDesigner.aspx и назначьте ее стартовой
Запустите страницу, чтобы проверить, что "Northwind"
В файле Web.Config скопируйте "Northwind" под другим именем "CloneNorthwind", после чего должно получиться следующее(рис ) Файл Web.Config после клонирования строки соединения<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="Northwind" connectionString="Data Source=localhost;
Initial Catalog=Northwind; user id=sa; password=;" />
<add name="CloneNorthwind" connectionString="Data Source=localhost;
Initial Catalog=Northwind; user id=sa; password=;" />
</connectionStrings>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Измените в файле Web.Config имя строки соединения "Northwind" на несуществующее имя, например "Northwind1" и вновь запустите страницу. Теперь страница выдает ошибку, поскольку "Northwind"Пусть теперь это ошибочное имя строки соединений пока побудет в файле Web.Config, а мы попробуем запустить "CloneNorthwind", которая у нас есть.
Откройте страницу на редактирование в режиме Design и выделите на ней объект ObjectDataSource1
Переведите панель Properties в режим редактирования событий и
Заполните обработчик так, чтобы окончательный код страницы ObjectDataSourceDesigner.aspx был следующим(рис ) Окончательный код страницы ObjectDataSourceDesigner.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void ObjectDataSource1_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = new EmployeeDB("CloneNorthwind");
}
</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"
SelectMethod="GetAllEmployees"
TypeName="EmployeeDB"
OnObjectCreating="ObjectDataSource1_ObjectCreating" />
<asp:ListBox ID="ListBox1" runat="server"
DataSourceID="ObjectDataSource1" DataTextField="LastName" />
<asp:GridView ID="GridView1" runat="server"
DataSourceID="ObjectDataSource1" />
</div>
</form>
</body>
</html>
Запустите страницу ObjectDataSourceDesigner.aspx и убедитесь, что опять все заработало, поскольку новую
Верните в файле Web.Config прежнее имя "Northwind" строке соединения, поскольку его используют все наши предыдущие страницы (строку с именем "CloneNorthwind" также оставьте для работы этого примера)По синтаксису настройки компонента мы не можем использовать ни параметризованный SelectMethod, InsertMethod, DeleteMethod и UpdateMethod можно присваивать только имя метода. Реальные же методы пользовательского класса могут содержать параметры. Например, в нашем классе EmployeeDB содержатся следующие параметризованные методы:
public int InsertEmployee(EmployeeDetails emp ) {...}public EmployeeDetails GetEmployee(int employeeID) {...}public void DeleteEmployee(int employeeID) {...}public void UpdateEmployee(int employeeID, string firstName ,string lastName , string titleOfCourtesy) {...}Мы воспользуемся методом GetEmployee(int employeeID), который ранее был описан так
public EmployeeDetails GetEmployee(int employeeID)
{
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("GetEmployee", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
cmd.Parameters["@EmployeeID"].Value = employeeID;
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
// Получить первую строку
reader.Read();
EmployeeDetails emp = new EmployeeDetails(
(int)reader["EmployeeID"],
(string)reader["FirstName"],
(string)reader["LastName"],
(string)reader["TitleOfCourtesy"]);
reader.Close();
return emp;
}
catch
{
throw new ApplicationException("Ошибка данныx.");
}
finally
{
con.Close();
}
}
Метод GetEmployee() вызывает GetEmployee с параметром, имеющую следующий вид
// Выбрать запись
string sql6 =
"CREATE PROCEDURE GetEmployee "
+ "@EmployeeID int "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees "
+ "WHERE EmployeeID = @EmployeeID";
Сейчас наша задача - создать страницу на основе компонента и пользовательского класса EmployeeDB, в которой при загрузке автоматически заполнялся бы список значениями EmployeeID из таблицы Employees, а при щелчке пользователя на конкретном
Создайте новую страницу с совмещенным кодом под именем ObjectDataSourceParameters.aspx и назначьте ее стартовой
Поместите на страницу из панели Toolbox следующие компоненты в порядке их перечисления:ObjectDataSource из вкладки Data<h2>Выберите ID сотрудника</h2>ListBox из вкладки StandardObjectDataSource из вкладки Data<h2>Данные о сотруднике</h2>DetailsView из вкладки DataНастроим компоненты страницы ObjectDataSourceParameters.aspx декларативным способом в режиме Design через панель Properties.
Выделите первый источник ObjectDataSource1 и установите для него следующие свойстваSelectMethod="GetAllEmployees" - автоматически вызываемый методTypeName="EmployeeDB" - применяемый пользовательский класс
Выделите список ListBox1 и установите для него следующие свойстваDataSourceID="ObjectDataSource1" - подключенный DataTextField="EmployeeID" - видимые данные спискаAutoPostBack ="True" - инициирует обратную отсылку спискаRows =9 - количество видимых строкWidth =100 - ширина в
Выделите второй источник ObjectDataSource2 и установите для него следующие свойстваSelectMethod="GetEmployee" - автоматически вызываемый методTypeName="EmployeeDB" - применяемый пользовательский класс
Щелчком на кнопке ( ...) в поле свойства Работа этого окна трансформируется в следующий дескрипторный код разметочной части страницы
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server"
SelectMethod="GetEmployee" TypeName="EmployeeDB"
OnSelecting="ObjectDataSource2_Selecting" >
<SelectParameters>
<asp:ControlParameter ControlID="ListBox1"
Name="employeeID" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
Имя для передаваемого в источник ObjectDataSource2 параметра должно повторять имя
public EmployeeDetails GetEmployee(int employeeID) {...}
поскольку источник допускает
Поэтому порядок следования ожидаемых параметров в настройках самого , их типы и регистр не учитываются, главное - точные имена и их количество. В каком регистре набирается имя параметра при декларативном объявлении в разметочной части страницы - значения не имеет, лишь-бы оно повторяло имя
Выделите элемент отображения данных DetailsView1 и установите для него следующие свойстваDataSourceID="ObjectDataSource2"AutoGenerateRows="False" - подавляет самостоятельное генерирование строк для всех полей без
Запустите страницу ObjectDataSourceParameters.aspx и получите ошибку выполнения!!!Дело здесь в том, что когда страница запрашивается в первый раз, нет никакого выбранного значения в элементе ListBox1, но элемент ObjectDataSource2 все равно вызовет метод GetEmployee() с employeeID. Это и вызовет генерацию исключения в поиске данных. Ситуацию можно исправить, если перехватить попытку привязки в элементе ObjectDataSource2 и явно отменить ее, когда параметр employeeID не определен.
Для этого нужно обработать событие , которое как раз происходит перед выполнением InputParameters и не обнаружим в ней параметра employeeID, то работу ObjectDataSource2 нужно будет прервать.
Создайте в панели Properties для события ObjectDataSource2.Selecting обработчик, который заполните так, чтобы окончательный код страницы ObjectDataSourceParameters.aspx был следующим<%@ Page Language="C#" %>
<script runat="server">
protected void ObjectDataSource2_Selecting(object sender,
ObjectDataSourceSelectingEventArgs e)
{
if (e.InputParameters["employeeID"] == null)
e.Cancel = true;
}
</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"
SelectMethod="GetAllEmployees" TypeName="EmployeeDB" />
<h2>
Выберите ID сотрудника</h2>
<asp:ListBox ID="ListBox1" runat="server" AutoPostBack="True"
DataSourceID="ObjectDataSource1" DataTextField="EmployeeID"
Rows="9" Width="100px" />
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server"
SelectMethod="GetEmployee" TypeName="EmployeeDB"
OnSelecting="ObjectDataSource2_Selecting" >
<SelectParameters>
<asp:ControlParameter ControlID="ListBox1"
Name="employeeID" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
<h2>
Данные о сотруднике</h2>
<asp:DetailsView ID="DetailsView1" runat="server"
Height="50px" Width="125px" DataSourceID="ObjectDataSource2"
AutoGenerateRows="False" >
<Fields>
<asp:BoundField DataField="LastName"
HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="TitleOfCourtesy"
HeaderText="TitleOfCourtesy" SortExpression="TitleOfCourtesy" />
<asp:BoundField DataField="EmployeeID"
HeaderText="EmployeeID" SortExpression="EmployeeID" />
<asp:BoundField DataField="FirstName"
HeaderText="FirstName" SortExpression="FirstName" />
</Fields>
</asp:DetailsView>
</div>
</form>
</body>
</html>
Элемент управления отображает только одну запись в виде таблицы с двумя столбцами, один из которых содержит имена поле, второй - их значения.
Исполните страницу ObjectDataSourceParameters.aspx и получите результатВыберите ID сотрудника

Данные о сотруднике
| Снетков | |
| TitleOfCourtesy | Доцент 007 |
| EmployeeID | 9 |
| Владимир |
Аналогичным образом можно задействовать и другие методы нашего пользовательского класса EmployeeDB, имеющие параметры:
public int InsertEmployee(EmployeeDetails emp ) {...}public void DeleteEmployee(int employeeID) {...}public void UpdateEmployee(int employeeID, string firstName , string lastName , string titleOfCourtesy) {...}Продемонстрируем возможность подключения к метода UpdateEmployee() пользовательского класса EmployeeDB, предназначенного для обновления записей таблицы Employees. За одно посмотрим, как правильно вызвать как параметр.
Вначале используем метод UpdateEmployee() в том виде с четырьма параметрами, как он был разработан нами ранее. Для сокращения работы используем часть наработок страницы SqlDataSourceUpdates.aspx. Метод UpdateEmployee() реализует SQL-команду UpdateEmployee, имеющей следующий вид
// Обновление записи
string sql3 =
"CREATE PROCEDURE UpdateEmployee "
+ "@EmployeeID int, "
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "UPDATE Employees "
+ "SET "
+ "FirstName = @FirstName,"
+ "LastName = @LastName,"
+ "TitleOfCourtesy = @TitleOfCourtesy "
+ "WHERE EmployeeID = @EmployeeID";
Сам существующий метод UpdateEmployee() описывается так в файле App_Code/UpdateEmployeeDB.cs
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();
}
}
Скопируйте страницу SqlDataSourceUpdates.aspx с именем ObjectDataSourceUpdates1.aspx и назначьте ее стартовой
Запустите страницу ObjectDataSourceUpdates1.aspx на выполнение и удостовертесь, что она работоспособна
Удалите элемент SqlDataSource1 и на его месте расположите объект ObjectDataSource1
Настройте объект ObjectDataSource1 следующим образомTypeName="EmployeeDB"SelectMethod="GetAllEmployees"UpdateMethod="UpdateEmployee"
Объект GridView1 подкорректируйте так:DataSourceID="ObjectDataSource1" - поменять подключаемый <asp :BoundField DataField ="City" HeaderText="Проживает" /> - удалить строку с отсутствующим в SQL-команде полем<asp :BoundField DataField ="TitleOfCourtesy" HeaderText="Статус" /> - изменить имя поля на имеющееся в SQL-командеВ окончательном виде страница ObjectDataSourceUpdates1.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"
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>
Метод UpdateEmployee() автоматически получает от объекта отображения GridView1 значения параметров для обновления за счет того, что имена Employees поля.
Исполните страницу ObjectDataSourceUpdates1.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 |
Исходный вариант метода UpdateEmployee() имеет четыре аргумента, которые автоматически используются как параметры
Таким условиям удовлетворяет вспомогательный класс 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 вполне может служить каналом в таблицу при выполнении метода обновления, если его использовать в качестве аргумента этого метода. Дополним класс 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" - для указания того, по описанию какого класса создавать промежуточный объект для 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()К черту перегружаемые методы вместе с их стандартными именами аргументов, совпадающими с именами полей таблицы и порядком следования! Применим произвольные имена метода обновления и его аргументов (но количество аргументов оставим прежним, соответствующим количеству извлеченных в полей).
Такая свобода требует написания значений в терминах , в значения в терминах источника , передающего эти значения дальше в таблицу Employees для обновления конечных данных. Ранее мы подобную задачу решали на странице OtherNameParamUpdates.aspx применительно к элементу .
Добавьте в класс EmployeeDB файла App_Code/UpdateEmployeeDB.cs копию исходного метода с четырьмя параметрами и подкорректируйте его так (теперь в файле будут три метода обновления)(рис ) Новый метод обновления в классе EmployeeDB файла App_Code/UpdateEmployeeDB.csusing 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 с прежним именем
Щелкните мышью на треугольнике в правом верхнем углу объекта
Щелкните на единственной, пока, ссылке Configure Data Source (сконфигурировать ObjectDataSource1
На первой странице мастера из раскрывающегося списка выберите используемый класс
На новой странице вначале установите вкладку SELECT, через которую установите метод
Установите вкладку UPDATE, через которую установите наш новый метод обновления данных После щелчка на кнопке 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 | Редакция |
Аналогичным образом можно задействовать и другие оставшиеся методы нашего пользовательского класса EmployeeDB, имеющие параметры:
public int InsertEmployee(EmployeeDetails emp ) {...}public void DeleteEmployee(int employeeID) {...}Рассмотрим операцию вставки с применением пользовательского класса EmployeeDB. Эту операцию мы вправе добавить на страницу в дополнение к уже реализованной операции обновления. Особенность реализации метода вставки состоит в том, что он возвращает значение, указывающее содержимое поля EmployeeID. Это поле в таблице является ключевым и имеет свойство AutoIncrement (автоматическое увеличение). Его значение, возвращенное методом, можно проигнорировать, но можно и перехватывать и использовать для каких-нибудь целей, например извещения пользователя.
Технологию вставки новой и удаления существующей записи в таблице базы данных лучше рассмотреть на примере.
Создайте копию страницы ObjectDataSourceUpdates2.aspx с именем ObjectDataSourceFull.aspx и назначьте ее стартовой
Проверьте работоспособность начального варианта страницы ObjectDataSourceFull.aspxЭтот вариант страницы хорош тем, что в нем параметры между элементами согласованы стандартно по именам полей и нет
Добавьте после элемента GridView1 компонент LinkButton и создайте для него обработчик LinkButton1_Click()
В режиме Design Page_Load() страницы, в котором мы будем формировать сообщение о номере добавленной в таблицу записи
Поместите после элемента LinkButton1 компонент Label с именем lblInfo, в котором мы будем размещать сообщения для пользователя о добавленной или удаленной записи таблицы Employees
В режиме Design вызовите встроенную панель источника
После щелчка на кнопке Finish откажитесь от предложения скорректировать объект
Вызовите через свойство
Выделите элемент ObjectDataSource1 и через панель Properties создайте обработчик ObjectDataSource1_Deleting() для события Deleting, в котором мы будем перехватывать номер удаляемой из таблицы записиВ результате таких действий по ObjectDataSource1 оболочка добавит в его
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
TypeName="EmployeeDB" SelectMethod="GetAllEmployees"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnDeleting="ObjectDataSource1_Deleting">
<UpdateParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
<asp:Parameter Name="firstName" Type="String" />
<asp:Parameter Name="lastName" Type="String" />
<asp:Parameter Name="titleOfCourtesy" Type="String" />
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="GridView1"
Name="employeeID" Type="int32" />
</DeleteParameters>
</asp:ObjectDataSource>
Теперь скорректируем управляющий столбец объекта GridView1, чтобы добавить в его пользовательский интерфейс кнопку для возможности удаления записи. Кнопку добавим в форме Link.
Вызовите встроенный визуальный редактор для объекта
Выделите управляющий столбец "Изменить" и в поле CommandField properties установите значения следующих свойствButtonType=LinkDeleteText="Удалить"ShowDeleteButton="True"
Вспомним, что в
ADO.NET отслеживает это положение автоматически, но ей нужно указать первичный ключ. Для этого служит параметр DataKeyNames в элементе управления GridView1 (поскольку мы планируем удалять запись через него), в котором указывается строка с одним именем Employees является поле EmployeeID.
Переведите редактор страницы в режим Source и добавьте в заголовок элемента GridView1 параметр, назначающий ключевое поле редактируемой таблицыDataKeyNames="EmployeeID"
Выделите текстовую метку lblInfo и сбросьте свойство сохранения состояния EnableViewState="False", чтобы при каждом новом запросе ее значение очищалосьНа этом этап декларативной настройки страницы закончен. Теперь нужно заполнить созданные нами ранее обработчики соответствующим кодом.
Заполните обработчики событий так, чтобы окончательный код страницы ObjectDataSourceFull.aspx стал следующим(рис ) Окончательный код страницы ObjectDataSourceFull.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void LinkButton1_Click(object sender, EventArgs e)
{
EmployeeDB db = new EmployeeDB();
// Вставляем пустую запись и запоминаем ее номер
Session["recordNumber"] =
db.InsertEmployee(new EmployeeDetails(0, "", "", ""));
// Обновляем страницу без полного цикла,
Server.Transfer(Request.FilePath);
}
protected void Page_Load(object sender, EventArgs e)
{
if (Session["recordNumber"] != null)
{
lblInfo.Text = "Добавлена запись "
+ Session["recordNumber"].ToString();
Session.Remove("recordNumber");
}
}
protected void ObjectDataSource1_Deleting(object sender,
ObjectDataSourceMethodEventArgs e)
{
lblInfo.Text = "Удалена запись "
+ e.InputParameters["employeeID"].ToString();
}
</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="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnDeleting="ObjectDataSource1_Deleting">
<UpdateParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
<asp:Parameter Name="firstName" Type="String" />
<asp:Parameter Name="lastName" Type="String" />
<asp:Parameter Name="titleOfCourtesy" Type="String" />
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="GridView1"
Name="employeeID" Type="int32" />
</DeleteParameters>
</asp:ObjectDataSource>
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataSourceID="ObjectDataSource1"
DataKeyNames="EmployeeID">
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="TitleOfCourtesy" HeaderText="Статус" />
<asp:CommandField
CancelText="Отмена" EditText="Редакция" HeaderText="Изменить"
ShowEditButton="True" ShowHeader="True" UpdateText="Применить"
DeleteText="Удалить" ShowDeleteButton="True">
<HeaderStyle BackColor="Red" ForeColor="Yellow" />
</asp:CommandField>
</Columns>
</asp:GridView>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">
Вставка
</asp:LinkButton>
<br />
<asp:Label ID="lblInfo" runat="server" EnableViewState="False" />
</div>
</form>
</body>
</html>
Исполните страницу ObjectDataSourceFull.aspx и насладитесь тем, что она имеет функциональность полноценного редактора таблиц, тем более - удаленных (Ах да Большой Билл, ах да мала-ц-ц-а!). Один из экранов, генерируемых на стороне пользователя, будет таким| № п/п | Имя | Фамилия | Статус | Изменить |
|---|---|---|---|---|
| 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 | Редакция/Удалить |
| 10 | Редакция/Удалить |
Вставка
Добавлена запись 10
Ранее мы рассматривали пример SqlDataSourceParameters.aspx заполнял городами список, жестко привязанный с помощью спискового свойства DataSourceID. Второй источник отрабатывал один и тот же
В следующем примере попробуем расширить список добавлением в него еще одного пункта и при выборе пользователем этого добавленного , а также изменение
Сделайте копию страницы SqlDataSourceParameters.aspx с именем SqlDataSourceChange.aspx и назначьте ее стартовой
Выделите элемент DropDownList ID="lstCities" и очистите его свойство DataSourceID, тем самым мы отвяжем список от 
Page_Load()
Для второго источника SqlDataSource ID="sourceEmployees" через панель Properties создайте обработчик события Selecting
Заполните обработчики кодом так, чтобы окончательное описание страницы было следующим<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)// Первый запрос
{
// Инициировать запрос и привязать результаты
lstCities.DataSource = sourceEmployeeCities.Select(
DataSourceSelectArguments.Empty);
lstCities.DataBind();
// Добавить новый элемент в список
lstCities.Items.Add("Все города");
lstCities.SelectedIndex = lstCities.Items.Count - 1;
}
}
void sourceEmployees_Selecting(object sender,
SqlDataSourceSelectingEventArgs e)
{
if ((string)e.Command.Parameters["@City"].Value == "Все города")
{
// Очистить коллекцию параметров
e.Command.Parameters.Clear();
// Изменить команду
e.Command.CommandText = "SELECT EmployeeID, FirstName, LastName, "
+ "Title, City FROM Employees WHERE City!=''";
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT DISTINCT City FROM Employees" />
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName,
Title, City FROM Employees WHERE City=@City"
OnSelecting="sourceEmployees_Selecting">
<SelectParameters>
<asp:ControlParameter Name="City" ControlID="lstCities"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Приведенный пример демонстрирует плохую практику программирования, когда смешиваются декларативный и программный подход к привязке данных. На больших страницах это может привести к путанице и возникновению ошибок, а также плохой читабельности кода. К тому же, подставляемую команду желательно бы спрятать в хранимой процедуре.
Статический результат выполнения страницы SqlDataSourceChange.aspx следующий
Выберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 9 | Владимир | Снетков | Доцент ВАК | Красноярск |
Программировать стараться - с конкурентами распрощаться
Профессиональное Web-приложение всегда имеет дело с данными, которые могут храниться в базе данных, XML- или структурированном файле, или где-то еще. Правильное отображение этих данных на странице пользователя так же важно, как и их извлечение. ADO.NET имеет механизм
Привязка одного значения позволяет связать свойство элемента управления с местом на странице. Это место называется вычислимым выражением привязки данных. Различают вычислимые # - выражения и более общие $ - выражения <.
Выражение
Выражение <%#...%> (в <? или <?=...?> ). Если выражение Page.DataBind() в сценарии страницы. Если мы забудем это сделать, то выражение
Пример корректных # - выражений
<%# Request .Browser .Browser %><%# GetUserName(ID) %><%# variable %><%# "Дорогой " + "друг " + name %><%# 2 * PI * radius + cos (alpha ) %>Пример интерфейсной части страницы, использующей несколько выражений
<html> <body> <form method="post" runat="server"> <asp:Image ID="Image1" runat="server" ImageUrl='<%# FilePath %>' /><br /> <asp:Label ID="Label1" runat="server" Text="<%# FilePath %>" /><br /> <asp:TextBox ID="TextBox1" runat="server" Text='<%# GetFilePath() %>' /><br /> <asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="<%# LogoPath.Value %>" Font-Bold="true" Text="Show logo" /><br /> <input type="hidden" ID="LogoPath" runat="server" value="MyMy.png"> <b><%# FilePath %></b><br /> <img src="<%# GetFilePath() %>"> </form> </body> </html>
В приведенном коде выражение DataBind() страницы.
Приведем простой пример.
Создайте новый сайт с именем WebSite9 командой File/New/Web Site (шаблон ASP.NET Web Site )
Скопируйте из проекта WebSite8 файл Web.Config, который должен иметь такой вид(рис ) Содержимое файла Web.Config<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="Northwind" connectionString=
"Data Source=localhost; Initial Catalog=Northwind; user id=sa; password=;" />
</connectionStrings>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Добавьте к приложению новую страницу с совмещенным кодом и именем SingleValueBinding.aspx, назначьте страницу стартовой
Вызовите для корня Web-дерева контекстное меню и создайте каталог Pictures сайта командой New Folder
Скопируйте из каталога Pictures данной работы в каталог Pictures сайта два файла: MyPhoto.jpg и MyMy.png (или любые другие рисунки)
Наполните страницу SingleValueBinding.aspx следующим кодом(рис ) Код страницы SingleValueBinding.aspx <%@ Page Language="C#" %>
<script runat="server">
// Объявления переменных класса
string cat = "Васька", photo;
// Методы
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
Label1.Text = "<h1>Заполните поля и пошлите запрос</h1>";
pict.Src = "Pictures/MyPhoto.jpg";
}
else
{
Label1.Text = "<h1>Вот Вам такие ответы</h1>";
photo = "Pictures/MyMy.png";
pict.Border = 3;
}
}
public int AddFun(string a, string b)
{
try
{
return Convert.ToInt32(a) + Convert.ToInt32(b);
}
catch
{
Label1.Text = "<h1 style='color:red'>В поля вводите целые числа</h1>";
Label1.Text += "<hr style='height:10; color:red' />";
return 0;
}
}
protected void Button1_Click(object sender, EventArgs e)
{
this.DataBind();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Выражения привязки одного значения</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" Text="Label" />
<h2>
Кто сказал Мяу...?</h2>
<b style="color: Red">
<%# "Кот " + cat + "!" %>
</b>
<h2>
Сколько будет дважды-два?</h2>
<b style="color: Red">
<%# 2 * 2 %>
</b>
<h2>
Введите два <em>целых</em> числа<br />
и получите их сумму</h2>
<asp:TextBox ID="TextBox1" runat="server" />
+
<asp:TextBox ID="TextBox2" runat="server" />
= <b style="color: Red">
<%# AddFun(TextBox1.Text, TextBox2.Text) %></b>
<h2>Кто здесь изображен?</h2>
<img id="pict" runat="server" src="<%# photo %>" />
<br />
<br />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="Выполнить" />
</div>
</form>
</body>
</html>
При первой загрузке страницы в текстовую метку выводится начальный заголовок <h1> и установленное по умолчанию значение свойства src <. Все выражения DataBind() страницы. Он заставляет выполниться все выражения <.
Выполните страницу SingleValueBinding.aspx и убедитесь в работоспособности выражений Результат при начальной загрузке страницы:

Результат после обратной отсылки страницы:

Некоторые элементы управления библиотеки .NET Framework, служащие для отображения данных, позволяют привязать сразу несколько своих дочерних элементов к
<select>, включая HtmlSelect, ListBox и DropDownListCheckBoxList и RadioButtonList, генерирующие BulletedList, создающий нумерованный или Все они наследуют от System.Web.UI., который содержит свойства, необходимые для привязки множественного значения. Эти свойства приведены в таблице
| Свойство | Описание | |
|---|---|---|
|
Подключает ссылку на объект с данными (для загрузки методом DataBind() ), имеющими |
|
DataSourceID |
Присоединяется к уже загруженному объекту данных. Используется как . Оба свойства сразу применять нельзя |
|
DataTextField |
Содержит наименование поля (столбца) таблицы, значения которого будут отображаться списком | |
<select size="3" name="ListBox1" id="ListBox1">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
|
![]() |
|
DataValueField |
Содержит наименование поля (столбца) таблицы, значения которого будут загружены в список как атрибуты value, но пользователь их не увидит |
|
<select size="3" name="ListBox1" id="ListBox1">
<option value="1">Text1</option>
<option value="2">Text2</option>
</select>
|
![]() |
|
В свою очередь, класс ListControl наследует метод DataBind() от класса System.Web.UI., иницирующий привязку.
Для примера привязки множественного значения спроектируем страницу, в которой в качестве объекта, имитирующего (System., имеющий шаблонный метод IDictionary<TKey, TValue>.Add(TKey, TValue).
Добавьте к приложению страницу с неразделяемым кодом и именем RepeatedValueBinding.aspx
Заполните интерфейсную часть страницы следующим кодом<%@ Page Language="C#" %>
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<select runat="server" id="Select1"
datatextfield="Key" datavaluefield="Value" size="3" />
<select runat="server" id="Select2"
datatextfield="Key" datavaluefield="Value" />
<asp:ListBox runat="server" ID="ListBox1"
DataTextField="Key" DataValueField="Value" Rows="3" />
<asp:DropDownList runat="server" ID="DropDownList1"
DataTextField="Key" DataValueField="Value" />
<asp:RadioButtonList runat="server" ID="RadioButtonList1"
DataTextField="Key" DataValueField="Value" />
<asp:CheckBoxList runat="server" ID="CheckBoxList1"
DataTextField="Key" DataValueField="Value" />
<br />
<asp:Button runat="server" ID="GetSelection" Text="Получить выделенное" />
<br />
<br />
<asp:Literal runat="server" ID="Result" EnableViewState="false" />
</div>
</form>
</body>
</html>
Объявления первых двух статических списков нужно набирать вручную, чтобы подсказчик кода допускал к их атрибутам. Элемент управления все-равно будет заполняться при каждой обратной отсылке и отображать значения свойств выбранных дочерних элементов. Поэтому, чтобы не таскать состояние этого элемента с сервера на
Переведите редактор страницы в режим Design и Page_Load(), который заполните такprotected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
// Создать источник данных (коллекцию) с тремя элементами
Hashtable ht = new Hashtable(3);
// Добавить в коллекцию элементы по схеме: Add(Key, Value)
ht.Add("Иванов", "Value1");
ht.Add("Петров", "Value2");
ht.Add("Сидоров", "Value3");
// Связать элементы управления с источником данных
Select1.DataSource = ht;
Select2.DataSource = ht;
ListBox1.DataSource = ht;
DropDownList1.DataSource = ht;
RadioButtonList1.DataSource = ht;
CheckBoxList1.DataSource = ht;
// Загрузить данные в элементы управления
this.DataBind();
}
}
можно представить таблицей из двух столбцов. Первый столбец считается Key, второй - Value.
Запустите страницу, чтобы проверить работу механизма привязки множественного значения к списковым элементам управленияТеперь реализуем функциональность, чтобы при щелчке на кнопке элемент собирал и отображал информацию о выделенных
Создайте обработчик для кнопки Button и заполните его следующим кодомprotected void GetSelection_Click(object sender, EventArgs e)
{
try
{
Result.Text += "<li>В Select1 выбрано: "
+ "(\""
+ Select1.Items[Select1.SelectedIndex].Text // Key
+ "\", \""
+ Select1.Value + "\")"; // Value
Result.Text += "<li>В Select2 выбрано: "
+ "(\""
+ Select2.Items[Select2.SelectedIndex].Text // Key
+ "\", \""
+ Select2.Value + "\")"; // Value
Result.Text += "<li>В ListBox1 выбрано: "
+ "(\""
+ ListBox1.SelectedItem.Text // Key
+ "\", \""
+ ListBox1.SelectedItem.Value + "\")"; // Value
Result.Text += "<li>В DropDownList1 выбрано: "
+ "(\""
+ DropDownList1.SelectedItem.Text // Key
+ "\", \""
+ DropDownList1.SelectedItem.Value + "\")"; // Value
Result.Text += "<li>В RadioButtonList1 выбрано: "
+ "(\""
+ RadioButtonList1.SelectedItem.Text // Key
+ "\", \""
+ RadioButtonList1.SelectedItem.Value + "\")";// Value
// Проверяем флажки
int checkedCount = 0;
string checkString = "";
foreach (ListItem check in CheckBoxList1.Items)
{
if (check.Selected)
{
checkString += "(\""
+ check.Text // Key
+ "\", \""
+ check.Value + "\"); "; // Value
checkedCount++; // Считем выделенные флажки
}
}
if (checkedCount == 0)
Result.Text += "<li>В CheckBoxList1 ничего не выбрано!";
else
Result.Text += "<li>В CheckBoxList1 выбрано: " + checkString;
}
catch
{
Result.Text = "<h1 style='color:Red'>Выберите в каждом элементе</h1>";
}
}
Разница в коде доступа к <select>.
Выполните полностью готовую страницу, демонстрирующую работу механизма привязки множественного значения к списковым элементам управления, чтобы получить следующий результат
Предыдущий пример использует в качестве , потому что он реализует интерфейс
System..
В качестве :
System.Collections .ArrayList Microsoft.VisualBasic.Collection System.Collections .Hashtable System.Collections .Generic .Dictionary <TKey, TValue>System.Data.DataViewУчитывая, что DataReader представляет данные также в виде таблицы с именованными столбцами, мы можем так сформулировать DataReader будут загружены два нужных нам столбца: один из которых можно считать Key, другой - Value. В элементе управления свойству DataTextField нужно присвоить имя поля, отображаемого в списке, а свойству DataValueField - имя поля, неотображаемого в списке.
Приведем пример. Пусть мы хотим заполнить окно списка ListBox полными именами всех сотрудников, хранящихся в таблице Employees учебной базы данных Northwind. Чтобы получить два столбца DataReader, один из которых будет вычисляемый, нужно сформулировать
SELECT EmployeeID, TitleOfCourtesy + ' ' + FirstName + ' ' + LastName AS FullName FROM Employees
Добавьте к проекту новую страницу DataReaderListBinding.aspx с разделяемым кодом и назначьте ее стартовой
Оформите и настройте интерфейсную часть страницы DataReaderListBinding.aspx так, чтобы она имела следующее дескрипторное представление(рис ) Дескрипторное представление интерфейсной части страницы DataReaderListBinding.aspx<%@ Page Language="C#" AutoEventWireup="true"
CodeFile="DataReaderListBinding.aspx.cs"
Inherits="DataReaderListBinding" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListBox ID="ListBox1" runat="server" DataTextField="FullName"
DataValueField="EmployeeID" SelectionMode="Multiple" Rows="10" />
<br />
<br />
<asp:Button ID="GetSelection" runat="server" Text="Получить выделенное"
OnClick="GetSelection_Click" />
<br />
<br />
<asp:Literal ID="Result" runat="server" EnableViewState="False" />
</div>
</form>
</body>
</html>
Заполните файл поддержки DataReaderListBinding.aspx.cs следующим кодом(рис ) Код файла поддержки DataReaderListBinding.aspx.csusing System;
using System.Data;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
public partial class DataReaderListBinding : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
// Создать объекты Command и Connection
string connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
string sql = "SELECT EmployeeID, "
+ "TitleOfCourtesy + ' ' + FirstName + ' ' + LastName "
+ "AS FullName FROM Employees";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sql, con);
try
{
// Открыть соединение и получить DataReader
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
// Привязать DataReader к списку и заполнить список
ListBox1.DataSource = reader;
ListBox1.DataBind();
reader.Close();
}
finally
{
// Закрыть соединение
con.Close();
}
}
}
protected void GetSelection_Click(object sender, EventArgs e)
{
Result.Text = "<b>Выделены сотрудники:</b>";
Result.Text += "<ol>";
foreach (ListItem item in ListBox1.Items)
if (item.Selected)
Result.Text +=
String.Format("<li> (\"{0}\", \"{1}\")</li>", item.Text, item.Value);
Result.Text += "</ol>";
}
}
Здесь мы заполнили список только при первом запросе страницы, расчитывая, что далее заполненный список будет сохраняться в состоянии вида. Если в элементе ListBox1 отключить сохранение состояния вида, установив EnableViewState="False", то при обратной отсылке список окажется пустым (попробуйте!).
Исполните страницу DataReaderListBinding.aspx для получения следующего результата
Выделены сотрудники:
Если для DropDownList, CheckListBox или RadioButtonList вместо ListBox, то достаточно изменить объявление элемента управления в интерфейсной части страницы. Остальная часть кода останется прежней.
Кроме списковых элементов управления, которые можно использовать для отображения множественных данных, существуют более специализированные элементы управления, спроектированные специально для этих целей. К ним относятся , и . Кроме того, механизм привязки имеют и такие элементы, как , и , хотя и служат несколько для других целей.
Здесь мы поговорим об элементе управления , возможных способах его настройки и привязки к нему разных имеет свойство и метод DataBind(). Типовое объявление элемента в интерфейсной части страницы выглядит так:
<asp:GridView ID="GridView1" runat="server" />
Рассмотрим пример, в котором данные DataReader будут привязываться не к списковому элементу управления, а к .
Создайте новую страницу GridViewDataBind.aspx с разделяемым кодом и назначьте ее стартовой
Поместите на страницу из вкладки Data панели Toolbox элемент управления GridView
Откройте на редактирование файл GridViewDataBind.aspx.cs и заполните его следующим кодом(рис ) Код файла GridViewDataBind.aspx.csusing System;
using System.Data;
using System.Web.Configuration;
using System.Data.SqlClient;
using System.Web.UI.WebControls;
public partial class DataReaderListBinding : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// Создать объекты Command и Connection
string connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
string sql = "SELECT EmployeeID, FirstName, LastName, "
+ "Title, City FROM Employees";
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand(sql, con);
try
{
// Открыть соединение и получить DataReader
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
// Привязать DataReader к GridView
GridView1.DataSource = reader;
GridView1.DataBind();
reader.Close();
}
finally
{
// Закрыть соединение
con.Close();
}
}
}
Исполните страницу GridViewDataBind.aspx для получения следующего результат| EmployeeID | City | |||
|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma |
| 3 | Janet | Leverling | Sales Representative | Kirkland |
| 4 | Margaret | Peacock | Sales Representative | Redmond |
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 8 | Laura | Callahan | Redmond | |
| 9 | Dodsworth | Sales Representative | London |
В библиотеке .NET Framework имеется ряд классов, которые соединяются с любым поставщиком данных ADO.NET, облегчая IDataSource.

К
System.Web.UI.WebControls .ObjectDataSource - позволяет подключиться к пользовательскому классу доступа к даннымSystem.Web.UI.WebControls .SqlDataSource - позволяет подключиться к любому поставщику ADO.NETSystem.Web.UI.WebControls .SiteMapDataSource - позволяет подключиться к файлу System.Web.SiteMap, описывающему навигационную структуру Web-сайтаSystem.Web.UI.WebControls .XmlDataSource - позволяет подключиться к XML-файлуВсе эти классы представлены как элементы управления на вкладке Data панели Toolbox оболочки Visual Studio 2005 и являются новшеством библиотеки .NET Framework 2.0. Если перенести этот элемент на страницу, то он отображается серым цветом как невизуальный компонент страницы. В то же время в разметочной части страницы появляется соответствующий
System.Data.Common System.Data.SqlClientSystem.Data.OracleClientSystem.Data.OleDbSystem.Data.Odbc Чтобы манипулировать данными одной конкретной таблицы базы данных, требуется создать для нее свой
ConnectionStringProviderNameText или StoredProcedure ) в свойствах SelectCommandType, InsertCommandType, UpdateCommandType и DeleteCommandTypeSelectQuery, InsertQuery, UpdateQuery и DeleteQuery (Такие имена имеют свойства в панели Properties, которые в дескрипторном представлении SelectCommand, InsertCommand, UpdateCommand и DeleteCommand )Нам нужно определять команды только для тех типов действий, которые мы намерены выполнить. Так, например, если мы используем SelectQuery.
Приведем пример Employees учебной базы данных Northwind.
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />

Создав и настроив HtmlSelect, ListBox, DropDownList, CheckBoxList, RadioButtonList, BulletedList уже на Page_Load(). Более того, если выполнить команду Refresh Scheme встроенной панели Page.DataBind() в коде страницы для заполнения элементов отображения, не нужно - все будет выполняться автоматически при запуске страницы.
Создайте страницу с объединенным кодом и именем SqlDataSourceSimple.aspx. Назначьте ее стартовой
Из вкладки Data панели Toolbox добавьте на страницу неотображаемый элемент управления SqlDataSource , через который мы привяжем данные к элементу отображения
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления ListBox
Из вкладки Data панели Toolbox добавьте на страницу элемент управления GridView
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления Button
Настройте объекты страницы: SqlDataSource1, элемент отображения данных ListBox1, многофункциональный элемент отображения данных GridView1, кнопку обратной отсылки Button1 следующим образом(рис ) Разметочная часть страницы SqlDataSourceSimple.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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" /></div>
</form>
</body>
</html>
Исполните страницу SqlDataSourceSimple.aspx, чтобы получить следующий результат
| EmployeeID | City | |||
|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma |
| 3 | Janet | Leverling | Sales Representative | Kirkland |
| 4 | Margaret | Peacock | Sales Representative | Redmond |
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 8 | Laura | Callahan | Redmond | |
| 9 | Dodsworth | Sales Representative | London |

Все работает автоматически без необходимости написания кода (который нам тоже не страшен). на случай, если данные изменяются редко.
Если изменить свойство DataSourceMode (установлено по умолчанию) на DataReader и исполнить страницу, то в данном случае получим тот же самый результат. Режим DataSourceMode= работы DataSourceMode=DataReader, поскольку он поддерживает расширенную сортировку, фильтрацию и настройку . Однако, если стоит задача отображать большие экранные таблицы, то лучше использовать режим DataSourceMode=DataReader, потому что он более эффективно использует память сервера.
Применение
Приведем пример, в котором при выборе города в списковом элементе автоматически выбираются и отображаются в другом элементе все сотрудники, проживающие в данном городе. Мы будем использовать два элемента отображения, к каждому из которых привяжем по своему Employees
Создайте страницу с объединенным кодом и именем SqlDataSourceParameters.aspx. Назначьте ее стартовой
Удалите контейнер сценария <script runat="server">...</script > как ненужный для данного примера
Из вкладки Data панели Toolbox добавьте на страницу первый SqlDataSource , который будет поставлять список всех городов из таблицы Employees. Назовите его sourceEmployeeCities
Из вкладки Standard панели Toolbox добавьте на страницу элемент управления DropDownList, который будет отображать все города, выбранные источником sourceEmployeeCities из таблицы Employees. Назовите его lstCities
Из вкладки Data панели Toolbox добавьте на страницу второй Employees, проживающих в переданном ему из раскрывающегося списка lstCities через параметр городе. Назовите его sourceEmployees
Из вкладки Data панели Toolbox добавьте на страницу элемент управления GridView с именем GridView1, который будет отображать список сотрудников, проживающих в выбранном городе и полученных из источника sourceEmployees
Настройте объекты страницы так, как показано ниже.При добавлении параметров пользуйтесь удобным редактором оболочки, позволяющим создавать команды и определять параметры. Редактор вызывается при выделенном элементе второго источника sourceEmployees щелчком на кнопке ( ...) свойства SelectQuery в панели Properties

Обратите внимание, что обратную отсылку мы выполняем за счет включенного свойства раскрывающегося списка lstCities. Обратите также внимание, что правильный перенос строковой константы в свойстве SelectCommand второго источника не влияет на возвращаемые SQL-командой результаты.
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT DISTINCT City FROM Employees" />
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True" DataSourceID="sourceEmployeeCities"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName,
Title, City FROM Employees WHERE City=@City">
<SelectParameters>
<asp:ControlParameter Name="City" ControlID="lstCities"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Исполните страницу SqlDataSourceParameters.aspx для получения следующего результатаВыберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 9 | Dodsworth | Sales Representative | London |
Здесь мы всю
Вернемся к редактору команд и параметров, представленному ранее окном

После набора команды в области SELECT щелчок на кнопке Refresh Parameters сканирует введенную команду и заполняет другие области и раскрывающиеся списки редактора нужной информацией, из которой можно потом быстро выбрать требуемое значение. В списке source перечислены типы элементов, которые могут передавать значения параметров в
Cookie ControlForm Profile QueryStringSession В нашем случае используется элемент управления DropDownList, поэтому мы установили тип параметра Control.
Предыдущий пример можно разбить на две страницы, чтобы продемонстрировать способ QueryString. На первой странице мы определим списковый элемент управления, который отобразит все города, находящиеся в таблице Employees учебной базы данных Northwind. На второй странице будем отображать список сотрудников, проживающих в выбранном городе. Информацию о городе будем перенаправлять в источник на второй странице через
Создайте новую страницу с объединенным кодом и именем QueryParameter1.aspx. Назначьте ее стартовой
Поместите на страницу SqlDataSource , списочный элемент ListBox и кнопку Button
Настройте свойства элементов так, как показано ниже, включая обработчики, полученные Page_Load ) и на кнопке ( cmdGo_Click )(рис ) Разметочная часть страницы QueryParameter1.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
lstCities.SelectedIndex = 0;
}
protected void cmdGo_Click(object sender, EventArgs e)
{
Response.Redirect("QueryParameter2.aspx?selectCity="
+ lstCities.SelectedValue);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница выбора города</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="SELECT DISTINCT City FROM Employees">
</asp:SqlDataSource>
<h2>
Выберите город</h2>
<asp:ListBox ID="lstCities" runat="server"
DataSourceID="sourceEmployeeCities"
DataTextField="City">
</asp:ListBox>
<br />
<br />
<asp:Button ID="cmdGo" runat="server" Text="Применить"
OnClick="cmdGo_Click" />
</div>
</form>
</body>
</html>
Создайте новую страницу с объединенным кодом и именем QueryParameter2.aspx
Поместите на страницу SqlDataSource и элемент GridView
Настройте свойства элементов так, как показано ниже(рис ) Разметочная часть страницы QueryParameter2.aspx<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница проживающих сотрудников</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName, Title,
City FROM Employees WHERE City=@City">
<SelectParameters>
<asp:QueryStringParameter Name="City" QueryStringField="selectCity" />
</SelectParameters>
</asp:SqlDataSource>
<h2>
Проживающие сотрудники</h2>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceEmployees" >
</asp:GridView>
</div>
</form>
</body>
</html>
Исполните страницу QueryParameter1.aspx и убедитесь, что запрос, сформированный на ней и направленный странице QueryParameter2.aspx на обработку, дает тот же самый результат, что и в предыдущем примереМы уже говорили о достоинствах
Прежде всего, создадим и запишем в базу данных
Скопируйте командой Add Existing Item из приложения WebSite8 разработанную нами ранее страницу SaveStoredProcedure.aspx и переименуйте ее в
Откройте на редактирование страницу SaveStoredProcedure1.aspx и откорректируйте ее так(рис ) Код страницы SaveStoredProcedure1.aspx для нового примера<%@ Page Language="C#" %>
<script runat="server">
// Объявления хранимых процедур
// Выборка городов
string sql1 =
"CREATE PROCEDURE GetCityes "
+ "AS "
+ "SELECT DISTINCT City FROM Employees";
// Выборка сотрудников для выбранного города
string sql2 =
"CREATE PROCEDURE GetEmployeesByCity "
+ "@paramCity varchar(15) "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, Title, City "
+ "FROM Employees WHERE City=@paramCity";
protected void Page_Load(object sender, EventArgs e)
{
// Извлекли строку соединения из web.config
string connectString = System.Web.Configuration.WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
// Создали объект соединения
System.Data.SqlClient.SqlConnection con =
new System.Data.SqlClient.SqlConnection(connectString);
// Создали объект Command
System.Data.SqlClient.SqlCommand cmd =
new System.Data.SqlClient.SqlCommand();
// Настроили объект Command
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.Text;
lblInfo.Text = "";
// Открываем соединение в безопасном режиме
try
{
con.Open();
}
catch
{
con.Close();
return;
}
// Выполняем команды в безопасном режиме
// Удаляем процедуры на случай повторного запуска этой страницы
try
{
cmd.CommandText = "DROP PROCEDURE GetCityes";
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"DROP PROCEDURE GetCityes\"<br />";
}
catch { }
try
{
cmd.CommandText = "DROP PROCEDURE GetEmployeesByCity";
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"DROP PROC GetEmployeesByCity\"<br />";
}
catch { }
// Выполняем команды в безопасном режиме
// Добавляем в базу данных хранимые процедуры
try
{
cmd.CommandText = sql1;
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"CREATE PROCEDURE GetCityes\"<br />";
}
catch { }
try
{
cmd.CommandText = sql2;
cmd.ExecuteNonQuery();
lblInfo.Text += "Прошли \"CREATE PROCEDURE GetEmployeesByCity\"<br />";
}
finally
{
con.Close();
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:Label ID="lblInfo" runat="server" />
</form>
</body>
</html>
Исполните страницу SaveStoredProcedure1.aspx, чтобы добавить в базу данных Northwind две Теперь осталось воспользоваться этими
Скопируйте страницу SqlDataSourceParameters.aspx и присвойте ей имя StoredProcedureParam.aspx. Назначьте страницу StoredProcedureParam.aspx стартовой
Внесите в страницу StoredProcedureParam.aspx небольшие изменения, чтобы она стала такой(рис ) Код страницы StoredProcedureParam.aspx<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetCityes"
SelectCommandType="StoredProcedure">
</asp:SqlDataSource>
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True" DataSourceID="sourceEmployeeCities"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetEmployeesByCity"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:ControlParameter ControlID="lstCities"
Name="paramCity" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Исполните страницу StoredProcedureParam.aspx и убедитесь, что она выдает точно такие же результаты, как и страница SqlDataSourceParameters.aspxВыберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 5 | Steven | Buchanan | Sales Manager | London |
| 6 | Michael | Suyama | Sales Representative | London |
| 7 | Robert | King | Sales Representative | London |
| 9 | Dodsworth | Sales Representative | London |
Теперь попробуем проверить работу
Выделите в панели Solution Explorer сразу две страницы QueryParameter1.aspx и QueryParameter2.aspx и создайте их копии с именами QueryStoredProcParam1.aspx и QueryStoredProcParam2.aspx. Назначьте страницу QueryStoredProcParam1.aspx стартовой
Заполните обе новых страницы следующими поправками(рис ) Код страницы QueryStoredProcParam1.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
lstCities.SelectedIndex = 0;
}
protected void cmdGo_Click(object sender, EventArgs e)
{
Response.Redirect("QueryStoredProcParam2.aspx?selectCity="
+ lstCities.SelectedValue);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница выбора города</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetCityes"
SelectCommandType="StoredProcedure">
</asp:SqlDataSource>
<h2>
Выберите город</h2>
<asp:ListBox ID="lstCities" runat="server"
DataSourceID="sourceEmployeeCities"
DataTextField="City">
</asp:ListBox>
<br />
<br />
<asp:Button ID="cmdGo" runat="server" Text="Применить"
OnClick="cmdGo_Click" />
</div>
</form>
</body>
</html>
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Страница проживающих сотрудников</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="GetEmployeesByCity"
SelectCommandType="StoredProcedure">
<SelectParameters>
<asp:QueryStringParameter Name="paramCity" QueryStringField="selectCity" />
</SelectParameters>
</asp:SqlDataSource>
<h2>
Проживающие сотрудники</h2>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sourceEmployees" >
</asp:GridView>
</div>
</form>
</body>
</html>
Исполните страницу QueryStoredProcParam1.aspx и убедитесь, что получился тот же результат, что и в соответствующем примере без использования Любая среда исполнения программ при возникновении ошибки выдает соответствующее сообщение, которое для пользователя представляет набор непонятных символов. Задача прикладного программиста - предусмотреть в своем приложении перехват этого сообщения, распознавание его и замену на более понятные для пользователя рекомендации. Даже если код нашей страницы не содержит ошибок, все равно сбой может произойти по причинам, от нас не зависящим. Например, может быть не запущен во время запроса страницы
Сбой в работе сопровождается генерацией события, которое происходит сразу после возникновения ошибки. Сбой при выполнении запроса выбрасывает событие Selected, а при обновлении, вставке или удалении записей - события Updated, или Deleted соответственно. Мы можем предусмотреть обработку каждого из этих событий в отдельности или запланировать общий обработчик на любой из этих сбоев.
В обработчике ошибок можно получить доступ к объекту сгенерированного исключения через его свойство SqlDataSourceStatusEventArgs.Exception. Если после выброса исключения мы хотим подавить его далнейшее распространение, то в обработчике должны установить SqlDataSourceStatusEventArgs.ExceptionHandled в true.
В качестве примера предусмотрим общий обработчик возможных исключений на выполнение всех четырех операций выборки, обновления, вставки и
Создайте копию страницы SqlDataSourceSimple.aspx с именем SqlDataSourceException.aspx и назначьте ее стартовой
Откройте страницу SqlDataSourceException.aspx на редактирование в режиме Design и Page_Load()
В обработчике
Следуйте указаниям подсказчика кода и нажимайте клавишу
Указанным способом зарегистрируйте события (и создайте для каждого из них обработчики)SelectedUpdatedInserted DeletedПосле проведенных действий страница SqlDataSourceException.aspx должна выглядеть так
<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Selected);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Updated);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Inserted);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Deleted);
}
void SqlDataSource1_Deleted(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Inserted(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Updated(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
void SqlDataSource1_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}
</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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" /></div>
</form>
</body>
</html>
Оставьте только один обработчик, а остальные удалите
Измените имя оставшегося общего обработчика на SqlDataSource1_Error и внесите это имя в регистрацию каждого события, чтобы блок кода сценария стал таким<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
}
void SqlDataSource1_Error(object sender, SqlDataSourceStatusEventArgs e)
{
}
</script>
Теперь осталось обработать возможное исключение
Поместите в конец страницы текстовую метку Label с именем lblError
Заполните обработчик ошибки (рис ) Окончательный код страницы SqlDataSourceException.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource1.Selected += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Updated += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Inserted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
SqlDataSource1.Deleted += new SqlDataSourceStatusEventHandler(SqlDataSource1_Error);
}
void SqlDataSource1_Error(object sender, SqlDataSourceStatusEventArgs e)
{
if (e.Exception != null)
{
// Известить пользователя, что команда не была завершена
lblError.Text = "<h1 style='color:#FF0000'>"
+ "При исполнении запроса произошло исключение!</h1>";
// Известить систему, что ошибка обработана
e.ExceptionHandled = true;
}
}
</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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees" />
<asp:ListBox ID="ListBox1" runat="server" DataSourceID="SqlDataSource1"
DataTextField="FirstName" />
<br />
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1" />
<br />
<asp:Button ID="Button1" runat="server" Text="Обновить" />
<asp:Label ID="lblError" runat="server" />
</div>
</form>
</body>
</html>
Чтобы испытать обработчик исключения, внесите какую-нибудь ошибку в 
Чтобы дать возможность пользователю редактировать записи в механизме множественной , и имеют такие средства, которые можно в них включить.
Настройка возможностей редактирования состоит из двух шагов:
UpdateQuery, InsertQuery и DeleteQueryКакие
Приведем пример, в котором дадим возможность пользователю редактировать таблицу Employees учебной базы данных Northwind.
Скопируйте страницу SqlDataSourceSimple.aspx с именем SqlDataSourceUpdates.aspx и назначьте ее стартовой
Удалите из нее объекты списка ListBox1 и кнопки Button1, чтобы остались только SqlDataSource1 и элемент отображения GridView1
Исполните страницу, чтобы убедиться, что данные, извлеченные источником из таблицы Employees, по-прежнему отображаются в GridView1Теперь настроим источник на обновление данных.
Выделите в режиме Design SqlDataSource1 и в панели Properties щелкните на кнопке с многоточием в поле UpdateQuery, чтобы запустить редактор формирования SQL-команды обновления записей с параметрами
Заполните поле UPDATE command редактора строкой SQL-команды с параметрамиUPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID
После щелчка на кнопке Refresh Parameters автоматически заполнится поле , как показано на рисунке

После таких действий редактор параметров сгенерирует дополнительные поправки в настройку
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID" >
<UpdateParameters>
<asp:Parameter Name="FirstName" />
<asp:Parameter Name="LastName" />
<asp:Parameter Name="Title" />
<asp:Parameter Name="City" />
<asp:Parameter Name="EmployeeID" />
</UpdateParameters>
</asp:SqlDataSource>
Обратите внимание, что имена параметров, предваряемых символом @, мы выбрали совпадающими с именами полей таблицы. Это необходимо потому, что объект GridView1 после привязки к нему
Исполните страницу SqlDataSourceUpdates.aspx с внесенными на данном этапе настройками Теперь осталось настроить интерфейсный объект GridView1 на возможность редактирования данных. Для этого добавим к GridView1 дополнительный столбец с функциями управления редактированием записей.
Вызовите внутреннюю панель настройки объекта GridView1, как показано на рисунке, и выберите пункт Edit Columns 
Появится диалоговое окно Fields, которое предоставляет в удобном виде настройки столбцов объекта GridView1

Используя диалоговое окно Fields выполните следующее:Auto -generate fields , чтобы отключить неконтролируемое отображение всех столбцовSelected fields пять столбцов типа BoundField, которые будут связаны с DataField (имя связываемого поля в HeaderText (отображаемый на экране заголовок столбца)CommandField/Edit, Update, Cancel и задайте ему следующие свойства:EditText="Редакция"CancelText="Отмена"UpdateText="ПрименитьButtonType="Button "HeaderText="Изменить"HeaderStyle/BackColor="Red"HeaderStyle/ForeColor="Yellow"В результате таких опосредованных действий оболочка сформирует следующее описание объекта GridView1
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Отчество" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" HeaderText="Проживает" />
<asp:CommandField ButtonType="Button" HeaderText="Изменить"
ShowEditButton="True" ShowHeader="True"
EditText="Редакция" CancelText="Отмена" UpdateText="Применить" >
<HeaderStyle BackColor="Red" ForeColor="Yellow" />
</asp:CommandField>
</Columns>
</asp:GridView>
В итоге окончательный код страницы будет следующим
<%@ 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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@EmployeeID" >
<UpdateParameters>
<asp:Parameter Name="FirstName" />
<asp:Parameter Name="LastName" />
<asp:Parameter Name="Title" />
<asp:Parameter Name="City" />
<asp:Parameter Name="EmployeeID" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" 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>
Запустите страницу и испытайте ее функциональность. Можно спокойно редактировать записи, не написав при этом ни строчки кода - все делает встроенный механизм ASP.NETСтраница SqlDataSourceUpdates.aspx в действии может выглядеть так
| № п/п | Имя | Фамилия | Статус | Проживает | Изменить |
|---|---|---|---|---|---|
| 1 | Nancy | Davolio | Sales Representative | Redmond | |
| 2 | Andrew | Fuller | Vice President, Sales | Tacoma | |
| 3 | Janet | Leverling | Sales Representative | Kirkland | |
| 4 | Margaret | Peacock | Sales Representative | Redmond | |
| 5 | Steven | Buchanan | Sales Manager | London | |
| 6 | Michael | Suyama | Sales Representative | London | |
| 7 | Robert | King | Sales Representative | London | |
| 8 | Laura | Callahan | Redmond | ||
| 9 | Владимир | Снетков | Доцент 007 | Красноярск |
В добавленном столбце управления редактированием (его можно разместить на любом месте, изменив порядок следования для внесения изменений в базу данных.
Можно создать аналогичные InsertQuery и DeleteQuery. Чтобы разрешить, например, вставку в элементе отображения , нужно добавить управляющий столбец типа CommandField и установить его отображение в свойстве ShowInsertButton

В
Такая ситуация называется конкуренцией данных или конфликтом изменений. Для ее решения применяются разные способы, один из которых опирается на тот факт, что в элементе отображения хранятся как оригинальные значения полей, так и их последние изменения. Сам по умолчанию (например, @original_FirstName ), и измененными, носящими имя поля. Источник может понимать имена оригинальных параметров и с другим OldValuesParameterFormatString (например, xxx{0} ).
Принимая решение о сохранении конечных изменений в базе данных, мы можем сконфигурировать в
UpdateCommand="UPDATE Employees SET FirstName=@FirstName,
LastName=@LastName, Title=@Title, City=@City
FROM Employees WHERE EmployeeID=@original_EmployeeID
AND FirstName=@original_FirstName
AND LastName=@original_LastName
AND Title=@original_Title AND City=@original_City"
Здесь для проверки неизменности полей в базе данных применяются оригинальные параметры, переданные из в
Подобную проверку ConflictDetection с OverwriteChanges (заменять без проверки, установлено по умолчанию) на CompareAllValues (заменять только при совпадении всех оригинальных значений).
Ранее мы говорили, что необходимым условием правильной пересылки данных из в с целью обновления конечных данных должно быть совпадение имен параметров с именами полей таблицы. Но иногда может возникнуть необходимость применить для обновления конечных данных чью-то подходящую
Рассмотрим этот способ на примере.
Скопируйте страницу SqlDataSourceUpdates.aspx с именем OtherNameParamUpdates.aspx и назначьте ее стартовой
Проверьте, что страница OtherNameParamUpdates.aspx работает
Назовите параметры источника другими именами, отличными от имен полей, например так(рис ) Назначение параметрам команды обновления других имен<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@paramFirstName,
LastName=@paramLastName, Title=@paramTitle, City=@paramCity
FROM Employees WHERE EmployeeID=@paramEmployeeID" >
<UpdateParameters>
<asp:Parameter Name="paramFirstName" Type="string" />
<asp:Parameter Name="paramLastName" Type="string" />
<asp:Parameter Name="paramTitle" Type="string" />
<asp:Parameter Name="paramCity" Type="string" />
<asp:Parameter Name="paramEmployeeID" Type="string" />
</UpdateParameters>
</asp:SqlDataSource>
Запустите страницу OtherNameParamUpdates.aspx и убедитесь, что конечные обновления в базе данных не выполняются из за того, что измененные поля не передаются из GridView1 в SqlDataSource1Для решения задачи используем событие , которое возбуждается непосредственно перед подтверждением обновлений.
Перейдите в режим Design редактирования страницы OtherNameParamUpdates.aspx и Page_Load()
Зайдите в тело обработчика и начинайте регистрировать событие Updating SqlDataSource1.Updating +=и далее используя клавишу
Оболочка создаст правильную заготовку обработчика события Updating. Теперь можно полностью удалить обработчик Page_Load() как неиспользуемый.
Удалите ненужный теперь обработчик Page_Load()
Добавьте к описанию источника атрибут OnUpdating="SqlDataSource1_Updating"Здесь мы пошли более длинным, но универсальным путем создания заготовки обработчика SqlDataSource1_Updating(). Знакомый нам более короткий и традиционный путь - создать заготовку обработчика через панель Properties, при этом имя обработчика автоматически добавится в описание
Заполните обработчик события Updating так, чтобы страница имела следующий вид(рис ) Окончательный код страницы OtherNameParamUpdates.aspx<%@ Page Language="C#" %>
<script runat="server">
void SqlDataSource1_Updating(object sender, SqlDataSourceCommandEventArgs e)
{
// Передать значения нестандартным именам параметров
e.Command.Parameters["@paramFirstName"].Value =
e.Command.Parameters["@FirstName"].Value;
e.Command.Parameters["@paramLastName"].Value =
e.Command.Parameters["@LastName"].Value;
e.Command.Parameters["@paramTitle"].Value =
e.Command.Parameters["@Title"].Value;
e.Command.Parameters["@paramCity"].Value =
e.Command.Parameters["@City"].Value;
e.Command.Parameters["@paramEmployeeID"].Value =
e.Command.Parameters["@EmployeeID"].Value;
// Удалить из коллекции стандартные имена параметров
e.Command.Parameters.Remove(e.Command.Parameters["@FirstName"]);
e.Command.Parameters.Remove(e.Command.Parameters["@LastName"]);
e.Command.Parameters.Remove(e.Command.Parameters["@Title"]);
e.Command.Parameters.Remove(e.Command.Parameters["@City"]);
e.Command.Parameters.Remove(e.Command.Parameters["@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:SqlDataSource ID="SqlDataSource1" runat="server"
ProviderName="System.Data.SqlClient"
ConnectionString="<%$ connectionStrings:Northwind %>"
SelectCommand=
"SELECT EmployeeID, FirstName, LastName, Title, City FROM Employees"
UpdateCommand="UPDATE Employees SET FirstName=@paramFirstName,
LastName=@paramLastName, Title=@paramTitle, City=@paramCity
FROM Employees WHERE EmployeeID=@paramEmployeeID"
OnUpdating="SqlDataSource1_Updating" >
<UpdateParameters>
<asp:Parameter Name="paramFirstName" Type="string" />
<asp:Parameter Name="paramLastName" Type="string" />
<asp:Parameter Name="paramTitle" Type="string" />
<asp:Parameter Name="paramCity" Type="string" />
<asp:Parameter Name="paramEmployeeID" Type="string" />
</UpdateParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False" >
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="Title" HeaderText="Статус" />
<asp:BoundField DataField="City" 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>
Запустите страницу OtherNameParamUpdates.aspx и убедитесь, что она сохранила прежние способности обновления данных в базеПереходим к следующей части...
Старательно сопишь - значит победишь
Компонент находится на вкладке Data панели Toolbox. Он позволяет создавать декларативным (на . Но для корректного применения пользовательский класс доступа к данным, которым может быть и разработанный нами класс, должен подчиняться нескольким правилам:
ObjectDataSource создает его экземпляры по необходимости и уничтожает их за собой в конце каждого запросаIEnumerable Выполнение этих правил гарантирует, что
Для дальнейшего рассмотрения применим
На корне Web-дерева создайте папку App_Code командой контекстного меню Add ASP.NET Folder
На папке Add_Code выполните команду Website/Add Existing Item и скопируйте из папки WebSite8/App_Code все ее содержимое, которое представляет собой описание пользовательского класса EmployeeDB
Вспомним, что ранее мы поместили в базу данных с помощью страницы WebSite8/SaveStoredProcedure.aspx
Скопируйте в текущее приложение страницу WebSite8/SaveStoredProcedure.aspx, откройте ее и посмотрите, что // Объявления хранимых процедур
// Вставка записи
string sql1 =
"CREATE PROCEDURE InsertEmployee "
+ "@EmployeeID int OUTPUT,"
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "INSERT INTO Employees "
+ "(TitleOfCourtesy, LastName, FirstName, HireDate) "
+ "VALUES(@TitleOfCourtesy, @LastName, @FirstName, GETDATE()) "
+ "SET @EmployeeID = @@IDENTITY";
// Удаление записи
string sql2 =
"CREATE PROCEDURE DeleteEmployee "
+ "@EmployeeID int "
+ "AS "
+ "DELETE FROM Employees WHERE EmployeeID = @EmployeeID";
// Обновление записи
string sql3 =
"CREATE PROCEDURE UpdateEmployee "
+ "@EmployeeID int, "
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "UPDATE Employees "
+ "SET "
+ "FirstName = @FirstName,"
+ "LastName = @LastName,"
+ "TitleOfCourtesy = @TitleOfCourtesy "
+ "WHERE EmployeeID = @EmployeeID";
// Выбрать все
string sql4 =
"CREATE PROCEDURE GetAllEmployees "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees";
// Подсчитать число записей
string sql5 =
"CREATE PROCEDURE CountEmployees "
+ "AS "
+ "SELECT COUNT(EmployeeID) "
+ "FROM Employees";
// Выбрать запись
string sql6 =
"CREATE PROCEDURE GetEmployee "
+ "@EmployeeID int "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees "
+ "WHERE EmployeeID = @EmployeeID";
В их числе и процедура GetAllEmployees, которую реализует в пользовательском классе EmployeeDB одноименный метод GetAllEmployees(). Эта процедура извлекает из таблицы Employees записи четырех полей в порядке их следования в имя нашего пользовательского класса и имя метода, который реализует в классе нужный сам создаст экземпляр этого пользовательского класса и вызовет указанный метод. В результате, объект пользовательского класса будет заполнен данными, которые увидит пользователь через привязанные к компоненту элементы отображения.
Создайте новую страницу с совмещенным кодом и именем ObjectDataSourceSimple.aspx. Назначьте ее стартовой
Перенесите на страницу ObjectDataSourceSimple.aspx из панели Toolbox следующие компонентыObjectDataSource из вкладки DataListBox из вкладки StandardGridView из вкладки Data
Выполните простые настройки свойств компонентов, чтобы окончательный код страницы стал таким(рис ) Код страницы ObjectDataSourceSimple.aspx после декларативных настроек <%@ Page Language="C#" %>
<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"
SelectMethod="GetAllEmployees"
TypeName="EmployeeDB" />
<asp:ListBox ID="ListBox1" runat="server"
DataSourceID="ObjectDataSource1" DataTextField="LastName" />
<asp:GridView ID="GridView1" runat="server"
DataSourceID="ObjectDataSource1" />
</div>
</form>
</body>
</html>
Исполните страницу ObjectDataSourceSimple.aspx, чтобы получить следующий результат
| TitleOfCourtesy | EmployeeID | ||
|---|---|---|---|
| Davolio | Ms. | 1 | Nancy |
| Fuller | Dr. | 2 | Andrew |
| Leverling | Ms. | 3 | Janet |
| Peacock | Mrs. | 4 | Margaret |
| Buchanan | Mr. | 5 | Steven |
| Suyama | Mr. | 6 | Michael |
| King | Mr. | 7 | Robert |
| Callahan | Ms. | 8 | Laura |
| Снетков | Доцент 007 | 9 | Владимир |
Исключительно простой получилась . Никакого кода не пришлось писать. Прямо - работа для дизайнеров или кухарок! Но пользовательский-то класс EmployeeDB мы ранее с вами создали. Его просто здесь не видно - он работает за кулисами и вызывается по ссылке, указанной в свойстве TypeName компонента . Элементы отображения, в свою очередь, получают свою порцию данных через ссылку на заполненный , указанную в свойстве DataSourceID.
Компонент сам создает экземпляр пользовательского класса и мы не имеем возможности декларативно передать в него информацию через параметры конструктора. Но можно воспользоваться событиями компонента , чтобы обойти это ограничение.
Компонент имеет богатую модель событий, представленную ниже
System.Web.UI.WebControls .ObjectDataSource .DeletedSystem.Web.UI.WebControls .ObjectDataSource .DeletingSystem.Web.UI.WebControls .ObjectDataSource .Filtering System.Web.UI.WebControls .ObjectDataSource .Inserted System.Web.UI.WebControls .ObjectDataSource .Inserting System.Web.UI.WebControls .ObjectDataSource .ObjectCreatedSystem.Web.UI.WebControls .ObjectDataSource .ObjectCreatingSystem.Web.UI.WebControls .ObjectDataSource .ObjectDisposingSystem.Web.UI.WebControls .ObjectDataSource .SelectedSystem.Web.UI.WebControls .ObjectDataSource .SelectingSystem.Web.UI.WebControls .ObjectDataSource .UpdatedSystem.Web.UI.WebControls .ObjectDataSource .UpdatingЭти события можно разделить на две категории:
ing - происходят во время выполнения задачи и позволяют вмешаться в этот процесс, что-то настроить или прерватьed - происходят по завершении задачи и удобны для Если мы хотим передать компоненту уже инициализированный параметризованным .
Продолжим эксплуатировать наш класс EmployeeDB, в котором как раз есть параметризованный
using System;
using System.Web.Configuration;
public partial class EmployeeDB
{
private string connectionString;
public EmployeeDB()
{
// Извлечь из файла web.config строку соединения по умолчанию
connectionString = WebConfigurationManager.
ConnectionStrings["Northwind"].ConnectionString;
}
public EmployeeDB(string connectionStringCustom)
{
// Извлечь из файла web.config другую строку соединения
connectionString = WebConfigurationManager.
ConnectionStrings[connectionStringCustom].ConnectionString;
}
}
Скопируйте страницу ObjectDataSourceSimple.aspx под именем ObjectDataSourceDesigner.aspx и назначьте ее стартовой
Запустите страницу, чтобы проверить, что "Northwind"
В файле Web.Config скопируйте "Northwind" под другим именем "CloneNorthwind", после чего должно получиться следующее(рис ) Файл Web.Config после клонирования строки соединения<?xml version="1.0"?>
<configuration>
<connectionStrings>
<add name="Northwind" connectionString="Data Source=localhost;
Initial Catalog=Northwind; user id=sa; password=;" />
<add name="CloneNorthwind" connectionString="Data Source=localhost;
Initial Catalog=Northwind; user id=sa; password=;" />
</connectionStrings>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Измените в файле Web.Config имя строки соединения "Northwind" на несуществующее имя, например "Northwind1" и вновь запустите страницу. Теперь страница выдает ошибку, поскольку "Northwind"Пусть теперь это ошибочное имя строки соединений пока побудет в файле Web.Config, а мы попробуем запустить "CloneNorthwind", которая у нас есть.
Откройте страницу на редактирование в режиме Design и выделите на ней объект ObjectDataSource1
Переведите панель Properties в режим редактирования событий и
Заполните обработчик так, чтобы окончательный код страницы ObjectDataSourceDesigner.aspx был следующим(рис ) Окончательный код страницы ObjectDataSourceDesigner.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void ObjectDataSource1_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
{
e.ObjectInstance = new EmployeeDB("CloneNorthwind");
}
</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"
SelectMethod="GetAllEmployees"
TypeName="EmployeeDB"
OnObjectCreating="ObjectDataSource1_ObjectCreating" />
<asp:ListBox ID="ListBox1" runat="server"
DataSourceID="ObjectDataSource1" DataTextField="LastName" />
<asp:GridView ID="GridView1" runat="server"
DataSourceID="ObjectDataSource1" />
</div>
</form>
</body>
</html>
Запустите страницу ObjectDataSourceDesigner.aspx и убедитесь, что опять все заработало, поскольку новую
Верните в файле Web.Config прежнее имя "Northwind" строке соединения, поскольку его используют все наши предыдущие страницы (строку с именем "CloneNorthwind" также оставьте для работы этого примера)По синтаксису настройки компонента мы не можем использовать ни параметризованный SelectMethod, InsertMethod, DeleteMethod и UpdateMethod можно присваивать только имя метода. Реальные же методы пользовательского класса могут содержать параметры. Например, в нашем классе EmployeeDB содержатся следующие параметризованные методы:
public int InsertEmployee(EmployeeDetails emp ) {...}public EmployeeDetails GetEmployee(int employeeID) {...}public void DeleteEmployee(int employeeID) {...}public void UpdateEmployee(int employeeID, string firstName ,string lastName , string titleOfCourtesy) {...}Мы воспользуемся методом GetEmployee(int employeeID), который ранее был описан так
public EmployeeDetails GetEmployee(int employeeID)
{
SqlConnection con = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("GetEmployee", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@EmployeeID", SqlDbType.Int, 4));
cmd.Parameters["@EmployeeID"].Value = employeeID;
try
{
con.Open();
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SingleRow);
// Получить первую строку
reader.Read();
EmployeeDetails emp = new EmployeeDetails(
(int)reader["EmployeeID"],
(string)reader["FirstName"],
(string)reader["LastName"],
(string)reader["TitleOfCourtesy"]);
reader.Close();
return emp;
}
catch
{
throw new ApplicationException("Ошибка данныx.");
}
finally
{
con.Close();
}
}
Метод GetEmployee() вызывает GetEmployee с параметром, имеющую следующий вид
// Выбрать запись
string sql6 =
"CREATE PROCEDURE GetEmployee "
+ "@EmployeeID int "
+ "AS "
+ "SELECT EmployeeID, FirstName, LastName, TitleOfCourtesy "
+ "FROM Employees "
+ "WHERE EmployeeID = @EmployeeID";
Сейчас наша задача - создать страницу на основе компонента и пользовательского класса EmployeeDB, в которой при загрузке автоматически заполнялся бы список значениями EmployeeID из таблицы Employees, а при щелчке пользователя на конкретном
Создайте новую страницу с совмещенным кодом под именем ObjectDataSourceParameters.aspx и назначьте ее стартовой
Поместите на страницу из панели Toolbox следующие компоненты в порядке их перечисления:ObjectDataSource из вкладки Data<h2>Выберите ID сотрудника</h2>ListBox из вкладки StandardObjectDataSource из вкладки Data<h2>Данные о сотруднике</h2>DetailsView из вкладки DataНастроим компоненты страницы ObjectDataSourceParameters.aspx декларативным способом в режиме Design через панель Properties.
Выделите первый источник ObjectDataSource1 и установите для него следующие свойстваSelectMethod="GetAllEmployees" - автоматически вызываемый методTypeName="EmployeeDB" - применяемый пользовательский класс
Выделите список ListBox1 и установите для него следующие свойстваDataSourceID="ObjectDataSource1" - подключенный DataTextField="EmployeeID" - видимые данные спискаAutoPostBack ="True" - инициирует обратную отсылку спискаRows =9 - количество видимых строкWidth =100 - ширина в
Выделите второй источник ObjectDataSource2 и установите для него следующие свойстваSelectMethod="GetEmployee" - автоматически вызываемый методTypeName="EmployeeDB" - применяемый пользовательский класс
Щелчком на кнопке ( ...) в поле свойства Работа этого окна трансформируется в следующий дескрипторный код разметочной части страницы
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server"
SelectMethod="GetEmployee" TypeName="EmployeeDB"
OnSelecting="ObjectDataSource2_Selecting" >
<SelectParameters>
<asp:ControlParameter ControlID="ListBox1"
Name="employeeID" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
Имя для передаваемого в источник ObjectDataSource2 параметра должно повторять имя
public EmployeeDetails GetEmployee(int employeeID) {...}
поскольку источник допускает
Поэтому порядок следования ожидаемых параметров в настройках самого , их типы и регистр не учитываются, главное - точные имена и их количество. В каком регистре набирается имя параметра при декларативном объявлении в разметочной части страницы - значения не имеет, лишь-бы оно повторяло имя
Выделите элемент отображения данных DetailsView1 и установите для него следующие свойстваDataSourceID="ObjectDataSource2"AutoGenerateRows="False" - подавляет самостоятельное генерирование строк для всех полей без
Запустите страницу ObjectDataSourceParameters.aspx и получите ошибку выполнения!!!Дело здесь в том, что когда страница запрашивается в первый раз, нет никакого выбранного значения в элементе ListBox1, но элемент ObjectDataSource2 все равно вызовет метод GetEmployee() с employeeID. Это и вызовет генерацию исключения в поиске данных. Ситуацию можно исправить, если перехватить попытку привязки в элементе ObjectDataSource2 и явно отменить ее, когда параметр employeeID не определен.
Для этого нужно обработать событие , которое как раз происходит перед выполнением InputParameters и не обнаружим в ней параметра employeeID, то работу ObjectDataSource2 нужно будет прервать.
Создайте в панели Properties для события ObjectDataSource2.Selecting обработчик, который заполните так, чтобы окончательный код страницы ObjectDataSourceParameters.aspx был следующим<%@ Page Language="C#" %>
<script runat="server">
protected void ObjectDataSource2_Selecting(object sender,
ObjectDataSourceSelectingEventArgs e)
{
if (e.InputParameters["employeeID"] == null)
e.Cancel = true;
}
</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"
SelectMethod="GetAllEmployees" TypeName="EmployeeDB" />
<h2>
Выберите ID сотрудника</h2>
<asp:ListBox ID="ListBox1" runat="server" AutoPostBack="True"
DataSourceID="ObjectDataSource1" DataTextField="EmployeeID"
Rows="9" Width="100px" />
<asp:ObjectDataSource ID="ObjectDataSource2" runat="server"
SelectMethod="GetEmployee" TypeName="EmployeeDB"
OnSelecting="ObjectDataSource2_Selecting" >
<SelectParameters>
<asp:ControlParameter ControlID="ListBox1"
Name="employeeID" PropertyName="SelectedValue" />
</SelectParameters>
</asp:ObjectDataSource>
<h2>
Данные о сотруднике</h2>
<asp:DetailsView ID="DetailsView1" runat="server"
Height="50px" Width="125px" DataSourceID="ObjectDataSource2"
AutoGenerateRows="False" >
<Fields>
<asp:BoundField DataField="LastName"
HeaderText="LastName" SortExpression="LastName" />
<asp:BoundField DataField="TitleOfCourtesy"
HeaderText="TitleOfCourtesy" SortExpression="TitleOfCourtesy" />
<asp:BoundField DataField="EmployeeID"
HeaderText="EmployeeID" SortExpression="EmployeeID" />
<asp:BoundField DataField="FirstName"
HeaderText="FirstName" SortExpression="FirstName" />
</Fields>
</asp:DetailsView>
</div>
</form>
</body>
</html>
Элемент управления отображает только одну запись в виде таблицы с двумя столбцами, один из которых содержит имена поле, второй - их значения.
Исполните страницу ObjectDataSourceParameters.aspx и получите результатВыберите ID сотрудника

Данные о сотруднике
| Снетков | |
| TitleOfCourtesy | Доцент 007 |
| EmployeeID | 9 |
| Владимир |
Аналогичным образом можно задействовать и другие методы нашего пользовательского класса EmployeeDB, имеющие параметры:
public int InsertEmployee(EmployeeDetails emp ) {...}public void DeleteEmployee(int employeeID) {...}public void UpdateEmployee(int employeeID, string firstName , string lastName , string titleOfCourtesy) {...}Продемонстрируем возможность подключения к метода UpdateEmployee() пользовательского класса EmployeeDB, предназначенного для обновления записей таблицы Employees. За одно посмотрим, как правильно вызвать как параметр.
Вначале используем метод UpdateEmployee() в том виде с четырьма параметрами, как он был разработан нами ранее. Для сокращения работы используем часть наработок страницы SqlDataSourceUpdates.aspx. Метод UpdateEmployee() реализует SQL-команду UpdateEmployee, имеющей следующий вид
// Обновление записи
string sql3 =
"CREATE PROCEDURE UpdateEmployee "
+ "@EmployeeID int, "
+ "@FirstName varchar(10),"
+ "@LastName varchar(20),"
+ "@TitleOfCourtesy varchar(25) "
+ "AS "
+ "UPDATE Employees "
+ "SET "
+ "FirstName = @FirstName,"
+ "LastName = @LastName,"
+ "TitleOfCourtesy = @TitleOfCourtesy "
+ "WHERE EmployeeID = @EmployeeID";
Сам существующий метод UpdateEmployee() описывается так в файле App_Code/UpdateEmployeeDB.cs
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();
}
}
Скопируйте страницу SqlDataSourceUpdates.aspx с именем ObjectDataSourceUpdates1.aspx и назначьте ее стартовой
Запустите страницу ObjectDataSourceUpdates1.aspx на выполнение и удостовертесь, что она работоспособна
Удалите элемент SqlDataSource1 и на его месте расположите объект ObjectDataSource1
Настройте объект ObjectDataSource1 следующим образомTypeName="EmployeeDB"SelectMethod="GetAllEmployees"UpdateMethod="UpdateEmployee"
Объект GridView1 подкорректируйте так:DataSourceID="ObjectDataSource1" - поменять подключаемый <asp :BoundField DataField ="City" HeaderText="Проживает" /> - удалить строку с отсутствующим в SQL-команде полем<asp :BoundField DataField ="TitleOfCourtesy" HeaderText="Статус" /> - изменить имя поля на имеющееся в SQL-командеВ окончательном виде страница ObjectDataSourceUpdates1.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"
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>
Метод UpdateEmployee() автоматически получает от объекта отображения GridView1 значения параметров для обновления за счет того, что имена Employees поля.
Исполните страницу ObjectDataSourceUpdates1.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 |
Исходный вариант метода UpdateEmployee() имеет четыре аргумента, которые автоматически используются как параметры
Таким условиям удовлетворяет вспомогательный класс 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 вполне может служить каналом в таблицу при выполнении метода обновления, если его использовать в качестве аргумента этого метода. Дополним класс 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" - для указания того, по описанию какого класса создавать промежуточный объект для 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()К черту перегружаемые методы вместе с их стандартными именами аргументов, совпадающими с именами полей таблицы и порядком следования! Применим произвольные имена метода обновления и его аргументов (но количество аргументов оставим прежним, соответствующим количеству извлеченных в полей).
Такая свобода требует написания значений в терминах , в значения в терминах источника , передающего эти значения дальше в таблицу Employees для обновления конечных данных. Ранее мы подобную задачу решали на странице OtherNameParamUpdates.aspx применительно к элементу .
Добавьте в класс EmployeeDB файла App_Code/UpdateEmployeeDB.cs копию исходного метода с четырьмя параметрами и подкорректируйте его так (теперь в файле будут три метода обновления)(рис ) Новый метод обновления в классе EmployeeDB файла App_Code/UpdateEmployeeDB.csusing 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 с прежним именем
Щелкните мышью на треугольнике в правом верхнем углу объекта
Щелкните на единственной, пока, ссылке Configure Data Source (сконфигурировать ObjectDataSource1
На первой странице мастера из раскрывающегося списка выберите используемый класс
На новой странице вначале установите вкладку SELECT, через которую установите метод
Установите вкладку UPDATE, через которую установите наш новый метод обновления данных После щелчка на кнопке 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 | Редакция |
Аналогичным образом можно задействовать и другие оставшиеся методы нашего пользовательского класса EmployeeDB, имеющие параметры:
public int InsertEmployee(EmployeeDetails emp ) {...}public void DeleteEmployee(int employeeID) {...}Рассмотрим операцию вставки с применением пользовательского класса EmployeeDB. Эту операцию мы вправе добавить на страницу в дополнение к уже реализованной операции обновления. Особенность реализации метода вставки состоит в том, что он возвращает значение, указывающее содержимое поля EmployeeID. Это поле в таблице является ключевым и имеет свойство AutoIncrement (автоматическое увеличение). Его значение, возвращенное методом, можно проигнорировать, но можно и перехватывать и использовать для каких-нибудь целей, например извещения пользователя.
Технологию вставки новой и удаления существующей записи в таблице базы данных лучше рассмотреть на примере.
Создайте копию страницы ObjectDataSourceUpdates2.aspx с именем ObjectDataSourceFull.aspx и назначьте ее стартовой
Проверьте работоспособность начального варианта страницы ObjectDataSourceFull.aspxЭтот вариант страницы хорош тем, что в нем параметры между элементами согласованы стандартно по именам полей и нет
Добавьте после элемента GridView1 компонент LinkButton и создайте для него обработчик LinkButton1_Click()
В режиме Design Page_Load() страницы, в котором мы будем формировать сообщение о номере добавленной в таблицу записи
Поместите после элемента LinkButton1 компонент Label с именем lblInfo, в котором мы будем размещать сообщения для пользователя о добавленной или удаленной записи таблицы Employees
В режиме Design вызовите встроенную панель источника
После щелчка на кнопке Finish откажитесь от предложения скорректировать объект
Вызовите через свойство
Выделите элемент ObjectDataSource1 и через панель Properties создайте обработчик ObjectDataSource1_Deleting() для события Deleting, в котором мы будем перехватывать номер удаляемой из таблицы записиВ результате таких действий по ObjectDataSource1 оболочка добавит в его
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
TypeName="EmployeeDB" SelectMethod="GetAllEmployees"
UpdateMethod="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnDeleting="ObjectDataSource1_Deleting">
<UpdateParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
<asp:Parameter Name="firstName" Type="String" />
<asp:Parameter Name="lastName" Type="String" />
<asp:Parameter Name="titleOfCourtesy" Type="String" />
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="GridView1"
Name="employeeID" Type="int32" />
</DeleteParameters>
</asp:ObjectDataSource>
Теперь скорректируем управляющий столбец объекта GridView1, чтобы добавить в его пользовательский интерфейс кнопку для возможности удаления записи. Кнопку добавим в форме Link.
Вызовите встроенный визуальный редактор для объекта
Выделите управляющий столбец "Изменить" и в поле CommandField properties установите значения следующих свойствButtonType=LinkDeleteText="Удалить"ShowDeleteButton="True"
Вспомним, что в
ADO.NET отслеживает это положение автоматически, но ей нужно указать первичный ключ. Для этого служит параметр DataKeyNames в элементе управления GridView1 (поскольку мы планируем удалять запись через него), в котором указывается строка с одним именем Employees является поле EmployeeID.
Переведите редактор страницы в режим Source и добавьте в заголовок элемента GridView1 параметр, назначающий ключевое поле редактируемой таблицыDataKeyNames="EmployeeID"
Выделите текстовую метку lblInfo и сбросьте свойство сохранения состояния EnableViewState="False", чтобы при каждом новом запросе ее значение очищалосьНа этом этап декларативной настройки страницы закончен. Теперь нужно заполнить созданные нами ранее обработчики соответствующим кодом.
Заполните обработчики событий так, чтобы окончательный код страницы ObjectDataSourceFull.aspx стал следующим(рис ) Окончательный код страницы ObjectDataSourceFull.aspx<%@ Page Language="C#" %>
<script runat="server">
protected void LinkButton1_Click(object sender, EventArgs e)
{
EmployeeDB db = new EmployeeDB();
// Вставляем пустую запись и запоминаем ее номер
Session["recordNumber"] =
db.InsertEmployee(new EmployeeDetails(0, "", "", ""));
// Обновляем страницу без полного цикла,
Server.Transfer(Request.FilePath);
}
protected void Page_Load(object sender, EventArgs e)
{
if (Session["recordNumber"] != null)
{
lblInfo.Text = "Добавлена запись "
+ Session["recordNumber"].ToString();
Session.Remove("recordNumber");
}
}
protected void ObjectDataSource1_Deleting(object sender,
ObjectDataSourceMethodEventArgs e)
{
lblInfo.Text = "Удалена запись "
+ e.InputParameters["employeeID"].ToString();
}
</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="UpdateEmployee"
DeleteMethod="DeleteEmployee"
OnDeleting="ObjectDataSource1_Deleting">
<UpdateParameters>
<asp:Parameter Name="employeeID" Type="Int32" />
<asp:Parameter Name="firstName" Type="String" />
<asp:Parameter Name="lastName" Type="String" />
<asp:Parameter Name="titleOfCourtesy" Type="String" />
</UpdateParameters>
<DeleteParameters>
<asp:ControlParameter ControlID="GridView1"
Name="employeeID" Type="int32" />
</DeleteParameters>
</asp:ObjectDataSource>
<asp:GridView ID="GridView1" runat="server"
AutoGenerateColumns="False" DataSourceID="ObjectDataSource1"
DataKeyNames="EmployeeID">
<Columns>
<asp:BoundField DataField="EmployeeID" HeaderText="№ п/п" />
<asp:BoundField DataField="FirstName" HeaderText="Имя" />
<asp:BoundField DataField="LastName" HeaderText="Фамилия" />
<asp:BoundField DataField="TitleOfCourtesy" HeaderText="Статус" />
<asp:CommandField
CancelText="Отмена" EditText="Редакция" HeaderText="Изменить"
ShowEditButton="True" ShowHeader="True" UpdateText="Применить"
DeleteText="Удалить" ShowDeleteButton="True">
<HeaderStyle BackColor="Red" ForeColor="Yellow" />
</asp:CommandField>
</Columns>
</asp:GridView>
<asp:LinkButton ID="LinkButton1" runat="server" OnClick="LinkButton1_Click">
Вставка
</asp:LinkButton>
<br />
<asp:Label ID="lblInfo" runat="server" EnableViewState="False" />
</div>
</form>
</body>
</html>
Исполните страницу ObjectDataSourceFull.aspx и насладитесь тем, что она имеет функциональность полноценного редактора таблиц, тем более - удаленных (Ах да Большой Билл, ах да мала-ц-ц-а!). Один из экранов, генерируемых на стороне пользователя, будет таким| № п/п | Имя | Фамилия | Статус | Изменить |
|---|---|---|---|---|
| 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 | Редакция/Удалить |
| 10 | Редакция/Удалить |
Вставка
Добавлена запись 10
Ранее мы рассматривали пример SqlDataSourceParameters.aspx заполнял городами список, жестко привязанный с помощью спискового свойства DataSourceID. Второй источник отрабатывал один и тот же
В следующем примере попробуем расширить список добавлением в него еще одного пункта и при выборе пользователем этого добавленного , а также изменение
Сделайте копию страницы SqlDataSourceParameters.aspx с именем SqlDataSourceChange.aspx и назначьте ее стартовой
Выделите элемент DropDownList ID="lstCities" и очистите его свойство DataSourceID, тем самым мы отвяжем список от 
Page_Load()
Для второго источника SqlDataSource ID="sourceEmployees" через панель Properties создайте обработчик события Selecting
Заполните обработчики кодом так, чтобы окончательное описание страницы было следующим<%@ Page Language="C#" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)// Первый запрос
{
// Инициировать запрос и привязать результаты
lstCities.DataSource = sourceEmployeeCities.Select(
DataSourceSelectArguments.Empty);
lstCities.DataBind();
// Добавить новый элемент в список
lstCities.Items.Add("Все города");
lstCities.SelectedIndex = lstCities.Items.Count - 1;
}
}
void sourceEmployees_Selecting(object sender,
SqlDataSourceSelectingEventArgs e)
{
if ((string)e.Command.Parameters["@City"].Value == "Все города")
{
// Очистить коллекцию параметров
e.Command.Parameters.Clear();
// Изменить команду
e.Command.CommandText = "SELECT EmployeeID, FirstName, LastName, "
+ "Title, City FROM Employees WHERE City!=''";
}
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<h2>Выберите город</h2>
<asp:SqlDataSource ID="sourceEmployeeCities" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT DISTINCT City FROM Employees" />
<asp:DropDownList ID="lstCities" runat="server"
AutoPostBack="True"
DataTextField="City" />
<h2>Проживающие сотрудники</h2>
<asp:SqlDataSource ID="sourceEmployees" runat="server"
ConnectionString="<%$ connectionStrings:Northwind %>"
ProviderName="System.Data.SqlClient"
SelectCommand="SELECT EmployeeID, FirstName, LastName,
Title, City FROM Employees WHERE City=@City"
OnSelecting="sourceEmployees_Selecting">
<SelectParameters>
<asp:ControlParameter Name="City" ControlID="lstCities"
PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server"
DataSourceID="sourceEmployees" />
</div>
</form>
</body>
</html>
Приведенный пример демонстрирует плохую практику программирования, когда смешиваются декларативный и программный подход к привязке данных. На больших страницах это может привести к путанице и возникновению ошибок, а также плохой читабельности кода. К тому же, подставляемую команду желательно бы спрятать в хранимой процедуре.
Статический результат выполнения страницы SqlDataSourceChange.aspx следующий
Выберите город

Проживающие сотрудники
| EmployeeID | City | |||
|---|---|---|---|---|
| 9 | Владимир | Снетков | Доцент ВАК | Красноярск |
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.