Привязка данных ADO.NET
Использование ObjectDataSource для вставки и удаления записей
Аналогичным образом можно задействовать и другие оставшиеся методы нашего пользовательского класса 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 двойным щелчком на свободном месте Web-формы создайте обработчик Page_Load() страницы, в котором мы будем формировать сообщение о номере добавленной в таблицу записи
- Поместите после элемента LinkButton1 компонент Label с именем lblInfo, в котором мы будем размещать сообщения для пользователя о добавленной или удаленной записи таблицы Employees
- В режиме Design вызовите встроенную панель источника ObjectDataSource1 и щелчком на ссылке Configure Data Source вызовите мастер конфигурации источника данных. Проверьте правильность подключения методов во вкладках SELECT и UPDATE, затем подключите метод удаления во вкладке DELETE
- После щелчка на кнопке Finish откажитесь от предложения скорректировать объект GridView1
- Вызовите через свойство ObjectDataSource1.DeleteParameters окно визуального редактирования параметров команды удаления и настройте его так
- Выделите элемент 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.
- Вызовите встроенный визуальный редактор для объекта GridView1. Для этого щелкните на кнопке (пиктограмма треугольника) в правом верхнем углу визуального представления объекта, а затем на ссылке Edit Columns
-
Выделите управляющий столбец "Изменить" и в поле CommandField properties установите значения следующих свойств
- ButtonType=Link
- DeleteText="Удалить"
- ShowDeleteButton="True"
Вспомним, что в реляционных базах данных должна поддерживаться целостность данных. Это значит, что если таблицы находятся в отношении "главный-подчиненный", то при удалении записи в главной таблице, имеющей первичный ключ, нужно позаботиться об удалении всех записей связанной таблицы с идентичными значениями вторичных ключей.
ADO.NET отслеживает это положение автоматически, но ей нужно указать первичный ключ. Для этого служит параметр DataKeyNames в элементе управления GridView1 (поскольку мы планируем удалять запись через него), в котором указывается строка с одним именем ключевого поля или строка со списком ключевых полей, разделенных запятыми. В нашем случае первичным ключом в таблице Employees является поле EmployeeID.
-
Переведите редактор страницы в режим Source и добавьте в заголовок элемента GridView1 параметр, назначающий ключевое поле редактируемой таблицы
- DataKeyNames="EmployeeID"
- Выделите текстовую метку lblInfo и сбросьте свойство сохранения состояния EnableViewState="False", чтобы при каждом новом запросе ее значение очищалось
На этом этап декларативной настройки страницы закончен. Теперь нужно заполнить созданные нами ранее обработчики соответствующим кодом.
-
Заполните обработчики событий так, чтобы окончательный код страницы 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
Программное изменение запроса пользователя в SqlDataSource
Ранее мы рассматривали пример SqlDataSourceParameters.aspx выборки данных из таблицы в зависимости от выбранного пользователем города. Первый источник SqlDataSource заполнял городами список, жестко привязанный с помощью спискового свойства DataSourceID. Второй источник SqlDataSource отрабатывал один и тот же SQL-запрос с разными значениями параметра, полученными из списка в зависимости от выбора пользователя.
В следующем примере попробуем расширить список добавлением в него еще одного пункта и при выборе пользователем этого добавленного элемента списка изменить SQL-запрос. Привязку списка к источнику данных SqlDataSource, а также изменение SQL-запроса выполним программно.
- Сделайте копию страницы SqlDataSourceParameters.aspx с именем SqlDataSourceChange.aspx и назначьте ее стартовой
- Выделите элемент DropDownList ID="lstCities" и очистите его свойство DataSourceID, тем самым мы отвяжем список от источника данных
- Двойным щелчком на свободном месте Web-формы создайте обработчик загрузки страницы 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 следующий
Выберите город
Проживающие сотрудники