Украина, Киев |
Элементы управления 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