Опубликован: 13.07.2010 | Уровень: специалист | Доступ: платный
Самостоятельная работа 5:

Элементы управления Data в приложениях на C#

Редактирование и обновление данных с использованием связанных элементов управления

До сих пор мы создавали формы, позволяющие просматривать данные, но более важной задачей является обеспечение возможности для пользователя редактировать и обновлять данные в базе данных. Займемся этим.

План действий

Чтобы не терять прежние наработки, нужно создать копию формы и ее наращивать, как мы это делали в предыдущих случаях. Причем нужно иметь ввиду, что в конце выполнения этой лабораторной работы мы, возможно, создадим презентационную форму для запуска из нее любой из разработанных здесь форм. Да и промежуточные результаты иметь всегда неплохо под рукой.

Работу предыдущей формы в режиме просмотра данных будем считать естественным до тех пор, пока пользователь не пожелает начать редактирование. Для обеспечения этой возможности предусмотрим три кнопки, с помощью которых можно выполнить следующие действия:

  1. Кнопка Edit. Должна позволять переключиться из режима просмотра в режим редактирования текстовых полей. При этом должен меняться внешний вид полей, чтобы пользователь знал, какой из режимов включен.
  2. Кнопка Save. Должна обеспечить сохранение на сервере изменений, внесенных в данные. После записи нужно перейти в режим просмотра, считая, что пользователь закончил этап редактирования.
  3. Кнопка 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 наиболее распространены следующие типы проверки нарушения параллелизма и стратегий обновления данных

  1. Изменения заносятся в базу данных в том случае, если значение первичного ключа обновленной строки совпадает со значением первичного ключа существующей строки.
  2. Изменения заносятся в базу данных в том случае, если ни один из столбцов, обновленных данным пользователем, не был изменен никем другим с тех пор, как строка была считана данным пользователем.
  3. Изменения заносятся в базу данных в том случае, если ни один из столбцов строки не был изменен никем другим с тех пор, как строка была считана данным пользователем.
  4. Изменения заносятся в базу данных в том случае, если метка времени последнего обновления строки не изменилась с тех пор, как строка была считана данным пользователем. По своему смыслу этот тип проверки аналогичен предыдущему.

Функционирование среды 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
Александр Очеретяный
Александр Очеретяный
Украина, Киев
Анастасия Балыбердина
Анастасия Балыбердина
Украина, Киев, НТУУ КПИ