Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции ОТИ - копия.doc
Скачиваний:
3
Добавлен:
01.07.2025
Размер:
8.91 Mб
Скачать

Добавление фильтра записей

Вместо жёсткой привязки значений к переменным m_strFilter или m_strSort, давайте добавим элемент редактирования, позволяющий определить, какие записи необходимо отобразить, во время выполнения. Рассмотрим соответствующие шаги.

  1. Откроем проект MyFirst и загрузим в Dialog Editor форму IDD_MYFIRST_FORM. Расширим диалоговое окно и переместим существующие элементы управления вниз, освободив сверху место под новые элементы управления.

  2. Перетащим и установим на форму поле статического текста, элемент редактирования и кнопку. Разместим их, как показано на рис. 31.1.

  3. Установим заголовок элемента статического текста в "Country". Идентификатор ресурса элемента редактирования установим в IDC_COUNTRY_FILTER. Заголовком кнопки должен быть "&Filter", а её идентификатором ресурса — IDC_FILTER.

Рис. 31.1. Добавление полей фильтрации записей

Рис. 31.2. Подключение элемента редактирования фильтра

  1. С помощью ClassWizard добавим в элемент редактирования переменную. Назовём ее m_CountryFilter, категорию установим в Control, а тип – в CEdit. Когда окно будет выглядеть, как на рис. 31.2, нажмём на ОК. Затем закроем ClassWizard.

  2. Дважды щёлкнем на кнопке IDC_FILTER, чтобы создать в классе CMyFirstView новый обработчик OnFilter(). Введём код, показанный в листинге 31.1.

Листинг 31.1. Функция CMyFirstView::OnFilter()

void CMyFirstView::OnFilter()

{

// TODO: Add your control notification handler code here

CString filter ="";

m_CountryFilter.GetWindowText(filter);

if (filter =="")

{

m_pSet->m_strFilter="";

}

else

{

m_pSet->m_strFilter = "Country =’"+filter +"’";

}

m_pSet->Requery();

UpdateData(FALSE);

}

Сперва обработчик OnFilter() извлекает текст из элемента редактирования IDC_COUNTRY_FILTER с помощью функции GetWindowText(). Когда элемент редактирования пуст, код отбирает все записи, устанавливая m_pSet->m_strFilter в "". Если элемент редактирования содержит значение, код объединяет его со строкой "Country=", тем самым ограничивая диапазон значений, получаемых из базы данных.

После создания набора записей изменение его значений m_strFilter или m_strSort не приведет к изменению диапазона значений или порядка чередования значений в наборе записей. MFC читает значения m_strFilter и m_strSort npи получении данных. Чтобы заставить объект CMyFirstSet создать новый набор записей, следует вызвать его метод Requery().

После всего этого остается нерешенной одна небольшая проблема. Набор записей изменен, но программа все еще выводит запись из старого набора. Для обновления экрана потребуется перенести значения переменных набора записей, в элементы управления диалогового окна, вызвав UpdateData(FALSE).

Двигаясь дальше и запустим новую версию MyFirst. При первом запуске приложение получает все записи из таблицы TOVAR. Если в элементе редактирования COUNTRY ввести значение "Корея" и нажать на Filter, приложение выведет только тех заказчиков, у которых в поле COUNTRY установлено значение Корея.

Добавление и удаление записей

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

Для создания диалогового окна Add A Record выполним следующие инструкции:

  1. Убедимся, что проект MyFirst открыт, и выберем из главного меню Insert | Resource. При появлении нового диалогового окна Insert Resource, из списка Resource Type выберем Dialog, а затем нажмём на New.

  2. Установим заголовок диалогового окна в "Add New Record", а идентификатор ресурса - в IDD_ADD_NEW.

  3. Перетащим и установим на форме 7 элементов статическою текста и 7 элементов редактирования. Расположив элементы в порядке, показанном на рис. 31.3. Идентификаторы элементов статического текста оставим установленными в IDC_STATIC Заголовки элементов статического текста и идентификаторы ресурса каждого из элементов редактирования установим в соответствии с именами полей таблицы TOVAR. Например, первое поле редактирования должно получить идентификатор IDC_KOD_TOV.

Рис. 31.3. Создание диалогового окна Add A Record

  1. Удерживая клавишу Ctrl, дважды щелкнем на первом элементе редактирования IDC_KOD_TOV. ClassWizard предупредит об отсутствии класса, объявленного для ресурса диалога IDD_ADD_NEW. Выберем New Class и нажмём на ОК. Когда откроется диалоговое окно New Class, зададим имя CAddNew и породим класс от CDialog, как показано на рис. 31.4.

  2. Добавим переменные для каждого элемента управления диалогового окна Add New Record. Имя каждой из переменных зададим в соответствии с именем таких же переменных класса представления, если таковые существуют. Тип переменных установим в CString или другой соответственно и добавим проверку на корректность вводимых значений для гарантии того, что длина каждого поля соответствует длине связанной записи таблицы TOVAR.

  3. Откроем меню IDR_MAINFRAME в редакторе меню и добавим разделяющую полосу после пункта меню Last Record. Добавим два новых пункта меню. Первый пункт назовём "&Add New" и установим его идентификатор ресурса в ID_RECORD_ADD_NEW, как показано на рис.31.5. Заголовок второго пункта меню установим в "&Delete" и определим для него идентификатор ID_RECORD_DELETE.

  4. С помощью ClassWizard подключим к классу CMyFirstView обработчики COMMAND для ID_RECORD_ADD_NEW и ID_RECORD_DELETE; назовём их OnRecordAddNe() и OnRecordDelete(). Поместим в них выделенный код из листинга 31.2.

Рис. 31.4. Создание класса диалога CaddNew

Рис. 31.5. Создание пунктов меню Add New и Delete

Листинг 31.2.Функции OnRecordAddNew() и OnRecordDelete().

Void CMyFirstView:: OnRecordAddNew()

{// 1.Создание нового диалога Add New

CАddNew dlg;

if (dlg.DoModal()==IDOK)

{// 2.Убедиться, что обязательное поле не пусто

if (dlg.m_TOVAR.IsEmpty())

{

MessageBox(

"Cannot add without Tovar name");

return;

}

// 3. Добавить новую запись в набор

m_pSet->AddNew();

// 4. Передать значения полей из диалога в набор

m_pSet->m_KOD_TOV=dlg. m_KOD_TOV;

m_pSet->m_TOVAR =dlg. m_TOVAR;

m_pSet->m_CENA =dlg. m_CENA;

m_pSet->m_EI =dlg. m_EI;

m_pSet->m_COUNTRY =dlg. m_COUNTRY;

m_pSet->m_STAVKA_NDS= dlg. m_STAVKA_NDS;

m_pSet->m_NAL =dlg. m_NAL;

// 5. Записать изменения в базу данных

m_pSet->Update();

// 6. Переместиться на новую запись

m_pSet->MoveLast();

// 7. Обновить экран

UpdateData(FALSE);

}

}

Void CMyFirstView:: OnRecordDelete()

{

// Попытка удаления записи

try

{

m_pSet->Delete();

}

catch (CDBException* error)

{

AfxMessageBox(error->m_strError);

error->Delete();

m_pSet->MoveFirst();

UpdateData(FALSE);

return;

}

// Переместиться на новую запись

m_pSet->MoveNext();

if (m_pSet->IsEOF())

m_pSet->MoveLast();

UpdateData(FALSE);

}

  1. Установим следующую строку в начале MyFirstView.cpp, непосредственно после других операторов #include:

#include "AddNew.h"

  1. Откомпилируем и запустим приложение.

Как работает добавление записей

Для добавления в базу данных новой записи код создаёт новый объект диалогового окна CaddNew, а затем вызывает его функцию DoModal(). Если DoModal() возвращает IDОК, код пытается добавить новую запись, но сперва убеждается, что пользователь ввел обязательное имя компании. В противном случае выдается вежливое сообщение и выполняется выход. Здесь можно поместить и любые дополнительные проверки.

Для добавления новой записи в CRecordSet код обращается к функции AddNew(), создающей новую пустую запись. После создания новой записи функция OnRecordAddNew() передает каждое поле из диалогового окна в эту новую запись.

После добавления новой записи в набор она на самом деле не записывается и базу данных до тех пор, пока не будет вызвана функция Update(). Прежде чем пытаться обновить базу данных, необходимо вызвать IsUpdated(), чтобы проверить допустимость обновления. Обновление может потерпеть неудачу по многим причинам. Например, в случае использования для двух разных записей одинаковое значение KOD_TOV, появляется сообщение об ошибке.

После того как Update() сохранит данные в базе, можно перейти на новую запись, вызвав MoveLast(). Даже если набор записей отсортирован или фильтруется, новые записи всегда добавляются в конец набора. Если конкретная запись должна занять "свое место", после вызова Update() обратитесь к Requery(). Однако в таком случае не будет способа переместиться в позицию только что добавленной записи, поэтому ее придется искать по всей таблице.

Как работает удаление записей

Удаление записей намного проще добавления. Для этого достаточно вызвать функцию Delete(), удаляющую текущую запись из набора данных и затем выполняющую перемещение на следующую запись. В функции OnRecordDelete() перемещение на новую запись осуществляется при помощи MoveNext() с проверкой признака конца файла с использованием IsEOF(). Если IsEOF() возвращает TRUE, значит была удалена последняя запись и вместо MoveNext() следует вызвать MoveLast(). Может возникнуть соблазн переписать код следующим образом:

if (m_pSet->IsEof ())

m_pSet->MoveLast();

else

m_pSet->MoveNext();

Несмотря на рациональность приведённого кода, он работать не будет: признак конца файла не включается до тех пор, пока не будет предпринята попытка переместиться за последнюю запись.

Может показаться, что удаление записи — довольно безопасная операции, но это на самом деле это не так. Если вы удалите нужную информацию, к примеру, запись заказчика, который должен вам деньги, а вы не будете иметь, ни малейшего представления о том, кто бы это мог сделать.

Во избежание подобных проблем, в системы управления базами данных были введены правила ссылочной целостности (referential integrity rules), которые предотвращают удаление записей, от которых зависят другие записи. При попытке такого удаления генерируется исключение CDBException. В OnRecordDelete() функции Delete() помещена в блок C++ try-catch — при появлении ошибки программа выдает предупреждение и перемещается на первую запись.

Занятие №32

Лабораторная работа №10 «Использованием инструментальных средств Visual C++ для создания простейшего приложения работы с базой данных»

Цель: создание простейшего приложения баз данных типа "запросить-и-обновить" ("query-and-update") с использованием инструментальных средств Visual C++, исследование средств доступа к базам данных.

Вы узнаете, как подключиться к базе данных с помощью ODBC и как создать форму, позволяющую перемещаться по таблице базы данных и редактировать ее содержимое с иcпользованием AppWizard.

Упражнение 1. Регистрация в системе источника данных. Создание имени источника данных (Data Source Name)

Упражнение 2. Создание ODBC-приложения с помощью AppWizard

Упражнение 3. Создание формы