Опубликован: 13.07.2010 | Доступ: свободный | Студентов: 891 / 20 | Оценка: 4.40 / 4.20 | Длительность: 77:34:00
Самостоятельная работа 5:

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

Обработка ошибок с помощью связанных элементов управления

В процессе эксплуатации приложений и баз данных иногда приходится сталкиваться с ошибками времени выполнения. Обычно такие ошибки называют исключениями. При работе с базами данных исключения возникают в процессе ввода данных пользователем и обновления базы данных на сервере. Их правильная обработка является важной составляющей создания надежных приложений.

Если в программе не предусмотрено применение соответствующих средств обработки исключений, то в лучшем случае система выводит стандартное сообщение о возникшей ошибке, а в худшем - аварийно завершает свою работу или записывает в базу данных ошибочные данные. В среде Visual Studio .NET 2003 для обработки ошибок предусмотрены специальные классы типа Exception.

Исключения времени выполнения могут возникать почти в любой части приложения. Разработчику для их управления предлагаются конструкции языка try-catch-finally-throw (попытка-ловушка-наконец-бросок). Программа, имеющая такие конструкции, называется защищенной. При работе с этими конструкциями следует иметь ввиду следующее:

  1. Для объекта исключения может быть выбрано любое имя.
  2. Конкретные типы исключений происходят от базового класса System.Exception. Одним из таких производных классов является класс System.Data.OleDb.OleDbException, который мы будем ниже использовать.
  3. Оператор throw предназначен для прямого вызова из программы исключительной ситуации, чтобы при выполнении каких-то условий направить обработку по цепочке вызовов к ближайшему обработчику.
  4. Конструкция catch используется для перехвата конкретных исключений. В программе может быть предусмотрено несколько таких блоков для обработки всех возможных исключений, которые могут в ней возникнуть.
  5. Разработчику не стоит скупиться на применение средств управления исключениями, и вставлять их в код при каждом удобном случае по принципу: "чего бы не случилось - хуже не будет - до пенсии далеко", а также из соображений защиты от пользователя-дурака или системы-дуры. Он не должен надеяться на русское "авось пронесет и это не случится".
  6. Билл из Редмонда выполнил большую работу по созданию средств обработки исключений в среде .NET Framework на разных языках. Правильное примененение конструкций try-catch-finally-throw и классов поддержки из BCL позволяет разработчику обеспечить обработку ошибок любого уровня сложности.
  7. Исключения несут в себе большой объем информации, поэтому в программе может быть обеспечена исчерпывающая обработка всех возможных ошибок. В частности, может быть предусмотрена процедура централизованной регистрации ошибок или даже автоматическая передача сообщений разработчику по электронной почте (или на оленях) при возникновении ошибок в его приложении. Возможно, вы сталкивались в своих лабораторных работах с такой ситуацией, когда оболочка Visual Studio .NET 2003 от ваших праведных действий вдруг начинает метаться, дымиться, чесать затылок, рычать, морщить лоб и, наконец, в предсмертных судорогах тихо просить, чтобы студент Панасюк срочно написал письмо Большому Биллу.
  8. Блок try - это фрагмент кода, во время выполнения которого происходит отслеживание возникающих исключений. При возникновении исключения выполнение кода, определенного в блоке try, прерывается, и начинает выполняться код, определенный в ближайшем блоке цепочки блоков catch с подходящей настройкой. Если исключение не возникло при выполнении всего блока try, то следующие за ним блоки catch игнорируются.
  9. Необязательный блок finaly следует в конце блоков try/catch и выполняется всегда, не зависимо от того, сработало исключение или нет. Его главное назначение - гарантировать, что ресурсы, которые открыты потенциально опасным методом, будут обязательно освобождены. В реальных приложениях этот блок используется для освобождения памяти, закрытия файла, отключения от источника и данных - выполнения любых необходимых операций, связанных с корректным завершением программы при возникновении исключения.

Добавим средства защиты в наше приложение, пытаясь повысить его живучесть. Уязвимым местом в коде проекта является операция сохранения изменений в базе данных и возможность некорректного завершения приложения. В нашем коде эти операции находятся в обработчиках кнопок btnSave, btnDelete и во вспомогательной функции SaveRecord().

  • Найдите в коде файла Form5.cs функции
    • private void btnSave_Click(object sender, System.EventArgs e)
    • private void SaveRecord()
    • private void btnDelete_Click(object sender, System.EventArgs e)
  • Для быстрого поиска нужных разделов кода пользуйтесь раскрывающимся списком вверху редактора кода


  • Вставьте в функции необходимый код, который приведен ниже и выделен синим цветом.
//*****************************************************************
// Обработчик события Click кнопки Save
private void btnSave_Click(object sender, System.EventArgs e)
{
  // Блок обработки исключений
  try
  {
    SaveRecord();
  }
  catch(Exception saveException) // Имя объекта исключения произвольное
  {
    MessageBox.Show("Произошла следующая ошибка:\n" 
      + saveException.Message
      , "\nСохранение текущих изменений отклонено!");
    return;
  }
    
  ActivateEditing(false);
  
  // Добавлен код для загруки новой записи
  if(mbAddNew)
  {
    // Загрузка данных новой записи
    LoadList(); // Наша функция
    // Обновление отдельного набора данных
    RefreshIndividual(); // Наша функция
    mbAddNew = false;
  }
}
  
//*****************************************************************
// Сохранить изменения в базе данных
private void SaveRecord()
{
  // Блок обработки исключений
  try
  {
    // Применить класс BindingContext для завершения
    // текущего сеанса редактирования, чтобы иметь
    // возможность записать обновления в базу данных
    this.BindingContext[dsCustomerIndividual, "Customers"].EndCurrentEdit();
  
    // Обновить данные в кэше из набора данных dsCustomerIndividual
    // в поставщик данных odaCustomerIndividual
    odaCustomerIndividual.Update(dsCustomerIndividual, "Customers");
  
    // Передать данные из кэша поставщика данных в базу
    dsCustomerIndividual.AcceptChanges();
  }
  catch(Exception saveException)
  {
    // Генерируем исключение, которое будет обработано 
    // во внешнем блоке try-catch, вызывающем эту функцию
    throw saveException;
  }
}
  
//*****************************************************************
private void btnDelete_Click(object sender, System.EventArgs e)
{
  // Блок обработки исключений
  try
  {
    // Отменить строку для удаления с использованием
    // метода RemoveAt() класса BindingContext
    this.BindingContext[dsCustomerIndividual, "Customers"]
      .RemoveAt(BindingContext[dsCustomerIndividual, "Customers"].Position);
  
    // Обновить данные в кэше из набора данных dsCustomerIndividual
    // в поставщик данных odaCustomerIndividual
    odaCustomerIndividual.Update(dsCustomerIndividual, "Customers");
  
    // Передать данные из кэша поставщика данных в базу
    dsCustomerIndividual.AcceptChanges();
  }
  catch(System.Data.OleDb.OleDbException delException)
  {
    // Проверяем, не относится ли возникшее исключение
    // к конкретному типу 3621, которое свидетельствует
    // об ошибочной попытке удалить запись, тогда как
    // в другой таблице существуют связанные с ней записи
    if(delException.Errors[0].NativeError == 3621)
      MessageBox.Show("Призошла ошибка попытки \n удаления связанной записи!"
        ,"Ошибка удаления в таблице Customer"
        ,MessageBoxButtons.OK
        ,MessageBoxIcon.Exclamation);
    else
      MessageBox.Show("Неопознанная ошибка \n при удалении записи!"
        ,"Ошибка удаления в таблице Customer"
        ,MessageBoxButtons.OK
        ,MessageBoxIcon.Exclamation);
        
    return;
  }
  catch(Exception delException)
  {
    MessageBox.Show(delException.Message
      ,"Ошибка удаления в таблице Customer"
      ,MessageBoxButtons.OK
      ,MessageBoxIcon.Exclamation);
        
    return;
  }
  
  // Перезагрузить список
  LoadList();
  
  // Отобразить первую запись
  RefreshIndividual();
  
  // Отключить текстовые поля
  ActivateEditing(false);
}
Листинг 5.10. Код обработки возможных исключений при опасных действиях
  • Запретите в одном или обоих поставщиках данных изменения данных, постройте приложение и испытайте срабатывание установленной нами защиты от исключений. При проверке добавляйте строки, а затем удаляйте их, но не трогайте существующие записи, чтобы база соответствовала оригиналу для получения одинаковых со мной результатов.

При попытке сохранения или удаления данных наши обработчики исключений будут выдавать примерно такие сообщения




А само приложение, при этом, будет сохранять полную работоспособность, бодрость духа и даже не кашлять.

  • Верните свойства поставщиков данных изменять данные для возможности выполнения дальнейших этапов построения проекта.