Элементы управления Data в приложениях на C#
Редактирование и обновление данных с использованием связанных элементов управления
До сих пор мы создавали формы, позволяющие просматривать данные, но более важной задачей является обеспечение возможности для пользователя редактировать и обновлять данные в базе данных. Займемся этим.
План действий
Чтобы не терять прежние наработки, нужно создать копию формы и ее наращивать, как мы это делали в предыдущих случаях. Причем нужно иметь ввиду, что в конце выполнения этой лабораторной работы мы, возможно, создадим презентационную форму для запуска из нее любой из разработанных здесь форм. Да и промежуточные результаты иметь всегда неплохо под рукой.
Работу предыдущей формы в режиме просмотра данных будем считать естественным до тех пор, пока пользователь не пожелает начать редактирование. Для обеспечения этой возможности предусмотрим три кнопки, с помощью которых можно выполнить следующие действия:
- Кнопка Edit. Должна позволять переключиться из режима просмотра в режим редактирования текстовых полей. При этом должен меняться внешний вид полей, чтобы пользователь знал, какой из режимов включен.
- Кнопка Save. Должна обеспечить сохранение на сервере изменений, внесенных в данные. После записи нужно перейти в режим просмотра, считая, что пользователь закончил этап редактирования.
- Кнопка Cancel: Должна отменять режим редактирования с очисткой кэша без сохранения данных в базе.
На данном этапе мы задействуем класс BindingContext. Этот класс упрощает работу с элементами управления, связанных с данными. В дальнейшем можно применить также и класс BindingManagerBase, который обеспечивает синхронизацию наборов данных с элементами управления.
-
Создайте
копию предудущего файла Form3.cs и назовите его Form4.cs. -
Отключите
из проекта файл Form3.cs -
Замените
в коде Form4.cs все значения Form3 на Form4,
используя окно Replace in Files -
Для
проверки постройте проект и убедитесь, что функциональность
предыдущей формы сохранилась - значит мы не сделали ошибок. -
Поместите
на форму три кнопки, как показано на рисунке (свободное место
зарезервировано), и задайте им значения свойств, приведенные
в таблице
| Объект | Свойство | Значение |
|---|---|---|
| Button | Name | btnEdit |
| Text | &Edit | |
| Button | Name | btnSave |
| Text | &Save | |
| Button | Name | btnCancel |
| Text | &Cancel |
-
Выполните
команду Format/Lock Controls, чтобы предотвратить
случайные изменения элементов интерфейса на форме
-
Создайте
обработчики события Click для кнопок и
заполните их так
// Обработчик события Click кнопки Edit
private void btnEdit_Click(object sender, System.EventArgs e)
{
// Разрешить редактирование данных в кэше
ActivateEditing(true);
}
// Функция изменения свойств текстовых полей
private void ActivateEditing(bool bEnable)
{
// Только для чтения
txtCustomerID.ReadOnly =
txtCompanyName.ReadOnly =
txtContactName.ReadOnly =
txtContactTitle.ReadOnly =
txtAddress.ReadOnly =
txtCity.ReadOnly =
txtRegion.ReadOnly =
txtPostalCode.ReadOnly =
txtCountry.ReadOnly =
txtPhone.ReadOnly =
txtFax.ReadOnly = !bEnable;
// Стиль текстовых полей
if(bEnable)
{
txtCustomerID.BorderStyle =
txtCompanyName.BorderStyle =
txtContactName.BorderStyle =
txtContactTitle.BorderStyle =
txtAddress.BorderStyle =
txtCity.BorderStyle =
txtRegion.BorderStyle =
txtPostalCode.BorderStyle =
txtCountry.BorderStyle =
txtPhone.BorderStyle =
txtFax.BorderStyle = BorderStyle.Fixed3D;
}
else
{
txtCustomerID.BorderStyle =
txtCompanyName.BorderStyle =
txtContactName.BorderStyle =
txtContactTitle.BorderStyle =
txtAddress.BorderStyle =
txtCity.BorderStyle =
txtRegion.BorderStyle =
txtPostalCode.BorderStyle =
txtCountry.BorderStyle =
txtPhone.BorderStyle =
txtFax.BorderStyle = BorderStyle.FixedSingle;
}
}
// Обработчик события Click кнопки Save
private void btnSave_Click(object sender, System.EventArgs e)
{
SaveRecord();
ActivateEditing(false);
}
// Сохранить изменения в базе данных
private void SaveRecord()
{
// Применить класс BindingContext для завершения
// текущего сеанса редактирования, чтобы иметь
// возможность записать обновления в базу данных
this.BindingContext[dsCustomerIndividual, "Customers"].EndCurrentEdit();
// Обновить данные в кэше из набора данных dsCustomerIndividual
// в поставщик данных odaCustomerIndividual
odaCustomerIndividual.Update(dsCustomerIndividual, "Customers");
// Передать данные из кэша поставщика данных в базу
dsCustomerIndividual.AcceptChanges();
}
// Обработчик события Click кнопки Cancel
private void btnCancel_Click(object sender, System.EventArgs e)
{
// Для отмены текущей операции
// применяется класс BindingContext
this.BindingContext[dsCustomerIndividual, "Customers"].CancelCurrentEdit();
ActivateEditing(false);
}
Листинг
5.7.
Обработчики события Click для кнопок
-
Выделите
текстовое поле txtCustLimit и очистите в нем свойство Text,
чтобы список изначально заполнялся полностью
Вспомните, что при создании объекта odaCustomerIndividual мы настраивали мастер поставщика данных
При нажатии кнопки Advanced Options мы вызвали соответствующее окно и запретили изменение данных в самой базе
В результате выдавалось окно с возможностями поставщика данных, которое имело такой вид
Теперь пришла пора снять с адаптера свойство защиты изменений данных в базе!!!
-
В режиме
дизайна выделите в подвале формы поставщик данных odaCustomerIndividual и
в нижней части панели Properties щелкните по ссылке Configure
Data Adapter...
Появится мастер настройки поставщика данных, в котором дойдите до вкладки с кнопкой Advanced Options, щелкните на ней и установите режим обновления данных. Вид вкладки с результатами настройки перед нажатием кнопки Finish должен выглядеть так
-
Постройте
проект и удостоверьтесь в правильной работе добавленных возможностей. При проверке добавьте пару
символов в поле Company Name, а затем сотрите их, чтобы база
соответствовала оригиналу для получения одинаковых со мной
результатов.
При разработке кода функции SaveRecord() мы использовали обновление данных в базе в два этапа: вначале сохранили изменения в поставщике данных, и лишь потом дали команду на окончательное внесение изменений в саму базу. Такой подход реализован в среде ADO.NET для обеспечения отсоединенного подключения к базе данных.
Механизм работы таков: поставщик данных при выполнении запроса SELECT на выборку данных кратковременно подключается к базе данных, загружает в кэш найденные данные и сразу же отключается от базы. Это дает возможность работать с базой данных максимальному количеству пользователей. Поставщик данных после разъединения имитирует теперь собой базу данных в кэше оперативной памяти и пользователь работает с данными не замечая, что фактически работает с копией данных.
Пользователь в отсоединенном режиме может сохранять данные якобы в базе, но при каждом сохранении поставщик данных фактически создает у себя по несколько версий изменений, которые можно всегда отменить (типа уровней откатов). При окончательном сохранении изменений в базе данных разработчик через программирование поставщика данных может реализовать необходимую стратегию обновления и разрешения конфликтных ситуаций.
Механизм ADO.NET работы в отсоединенном режиме опирается на принцип оптимистического параллелизма обработки данных. Данные в самой базе не блокируются и могут потребляться сразу несколькими пользователями. Поставщики данных каждого пользователя периодически проверяют изменения подведомственных данных в базе и позволят сохранить изменения только тех данных, с которыми не работают в данный момент другие пользователи.
В SQL Server наиболее распространены следующие типы проверки нарушения параллелизма и стратегий обновления данных
- Изменения заносятся в базу данных в том случае, если значение первичного ключа обновленной строки совпадает со значением первичного ключа существующей строки.
- Изменения заносятся в базу данных в том случае, если ни один из столбцов, обновленных данным пользователем, не был изменен никем другим с тех пор, как строка была считана данным пользователем.
- Изменения заносятся в базу данных в том случае, если ни один из столбцов строки не был изменен никем другим с тех пор, как строка была считана данным пользователем.
- Изменения заносятся в базу данных в том случае, если метка времени последнего обновления строки не изменилась с тех пор, как строка была считана данным пользователем. По своему смыслу этот тип проверки аналогичен предыдущему.
Функционирование среды ADO.NET в отсоединенном режиме основано на создании временных данных в файле на языке XML. Чтобы убедиться в этом, загляните в панель Solution Explorer и вы увидите файлы с расширением .xsd и с именами созданных нами наборов данных. Откройте файл DataSet1.xsd через команду контекстного меню Open With/Source Code (Text) Editor и можно увидеть схему на XML, приведенную ниже
<?xml version="1.0" standalone="05_57"?>
<xs:schema id="DataSet1"
targetNamespace="http://www.tempuri.org/DataSet1.xsd"
xmlns:mstns="http://www.tempuri.org/DataSet1.xsd"
xmlns="http://www.tempuri.org/DataSet1.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
attributeFormDefault="qualified" elementFormDefault="qualified">
<xs:element name="DataSet1"
msdata:IsDataSet="true" msdata:Locale="ru-RU">
<xs:complexType>
<xs:choice maxOccurs="unbounded">
<xs:element name="Customers">
<xs:complexType>
<xs:sequence>
<xs:element name="CustomerID" type="xs:string" />
<xs:element name="CompanyName" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:choice>
</xs:complexType>
<xs:unique name="Constraint1" msdata:PrimaryKey="true">
<xs:selector xpath=".//mstns:Customers" />
<xs:field xpath="mstns:CustomerID" />
</xs:unique>
</xs:element>
</xs:schema>
Листинг
5.8.
Схема набора данных DataSet1 на языке XML







