На этом шаге мы рассмотрим алгоритм задания фильтра.
Мы упоминали, что набор записей можно фильтровать, задав в переменной-члене m_strFilter объекта набора записей строку с выражением WHERE. Далее показано, как применить эту методику так, чтобы приложение MyDBApp отображало выбранные из таблицы авторов записи, фильтруя их по идентификатору штата. Вы создадите пункт меню, позволяющий пользователю задавать для фильтрования набора записей код штата из таблицы авторов.
Рис.1. Создание пункта меню &Filter
Рис.2. Панель инструментов без удаленных кнопок
Рис.3. Создание функции-обработчика
Дальше Вы создадите диалоговое окно выбора штата Select State, в котором будут перечислены все коды штатов, указанные в таблице авторов.
Рис.4. Задание нового диалога
Рис.5. Внешний вид диалогового окна
Рис.6. Создание нового класса
Рис.7. Добавление переменной m_statelist
Рис.8. ClassWizard после добавления переменных
Рис.9. Подготовка к перегрузке функции
CDatabase aDB; try { aDB.OpenEx("DSN=MyDSN"); // Если применяется авторизация SQL Server, // укажите данные учетной записи, например // aDB.OpenEx("ODBC;DSN=MyDSN;UID=sa;PWD="); CRecordset aRS(&aDB); aRS.Open(CRecordset::forwardOnly,"SELECT DISTINCT state FROM authors"); while(!aRS.IsEOF()) { CString strValue; aRS.GetFieldValue(short(0), strValue); m_statelist.AddString(strValue); aRS.MoveNext(); } m_statelist.InsertString(0, "All records"); aRS.Close(); aDB.Close(); } catch(CDBException *ex) { TCHAR buf[255]; ex->GetErrorMessage(buf,255); CString strPrompt(buf); AfxMessageBox(strPrompt); }
Обратите внимание, что для выборки информации из базы данных эта функция использует локальные объекты CDatabase и CRecordset. Код создает набор записей с прокруткой в одном направлении - однократного просмотра вполне достаточно. Оператор SELECT, открывающий набор записей, содержит ключевое слово DISTINCT, указывающее, что в наборе должны присутствовать только уникальные записи. В результате каждый штат, упомянутый в таблице, в наборе будет представлен единственной записью.
Функция CRecordset::MoveNext() просматривает набор записей, пока CRecordset::IsEOF() не возвратит TRUE. В обязанности функции CRecordset::GetFieldValue() входит выборка значения поля "штат" в каждой строке. Она позволяет динамически выбирать из набора записей значение определенного поля по его индексу (который отсчитывается от нуля). Поскольку в данном случае функция возвращает только одно поле, его значение можно получить по индексу 0. Обратите внимание, как эта функция путем задания соответствующих переменных RFX позволяет непосредственно применять класс CRecordset и не создавать специальный производный класс.
Значения, извлеченные из строк набора, помещаются в поле со списком диалогового окна. Функция CListBox::InsertString() добавляет в начало списка пункт All records (Все записи).
Обратите внимание, что код работы с базой данных помеще блок try, а обработчик catch извлекает из объекта CDBException информацию, которая сообщается пользователю.
И наконец, Вы создадите функцию OnFilterState(), которая будет выполнять пункт State из меню Filter. Она открывает диалоговое окно Select State и фильтрует записи в соответствии с кодом штата, выбранным пользователем.
#include "StateDialog.h"
CStateDialog aSD; if (aSD.DoModal() == IDOK) { if (aSD.m_strState == "All records") m_myDBAppSet.m_strFilter = ""; else m_myDBAppSet.m_strFilter.Format("state = '%s'", aSD.m_strState); m_myDBAppSet.Requery(); POSITION pos = GetFirstViewPosition(); if (pos != NULL) { CView* pView = GetNextView(pos); ASSERT_VALID(pView); pView->UpdateData(FALSE); } }
Функция CRecordset::Requery() обновляет набор записей после изменения фильтра, после чего текущей становится первая первая запись набоpa. Важно удостовериться, что Вы вызываете функцию UpdateData() для обновления отображаемых значений в соответствии с данными новой текущей записи.
Вы можете реализовать возможность задавать фильтр набора на основе параметров времени выполнения, добавив вопросительные знаки (?) в качестве знаков подстановки:
m_myDBAppSet.m_strFilter = "state = ?";
Далее, во время работы приложения Вы можете обратиться к механизму RFX для замены знаков подстановки конкретными значениями. Подробнее о параметрах в наборах записей - в разделе "Recordset: parameterizing a Recordset (ODBC)" справочной системы Visual C++. Параметры намного эффективнее простой замены строки фильтра. При работе с параметрами базе данных нужно обработать только один SQL-оператор SELECT, а в случае набора с фильтром без параметров его придется выполнять при каждом изменении фильтра.
Текст этого приложения можно взять здесь (44,6 Кб).
Со следующего шага мы начнем знакомиться с ADO.