Интерфейс доступа к базам данных
Библиотека MFC предоставляет удобный интерфейс доступа к базам данных и высокий уровень абстракции от конкретных используемых средств DAO или ODBC. Для каждой открытой базы данных создается отдельный объект база данных (класса, производного от CDatabase или CDaoDatabase). Используя этот объект, можно выполнить подсоединение к базе данных. Другой объект библиотеки MFC - набор записей (класса, производного от CRecordset или CDaoRecordset) позволяет выполнять запросы и вносить изменения в таблицы базы данных. Классы DAO предоставляют также дополнительные возможности - использование объектов для работы со структурой таблицы (CDaoTableDef) и для сохраняемых запросов
(CDaoQueryDef).
Для отображения записей базы данных в рамках архитектуры документ-отображение реализованы классы отображений CDaoRecordView и CRecordView, производные от класса CView.
Рассмотрим пример SDI-приложения, разработанного на основе шаблона приложения, созданного AppWizard. Это приложение реализует доступ к таблице FoxPro.
Основными отличиями от SDI-приложения, рассмотренного нами в гл. 7 является: • использование в качестве базового класса объекта отображения класса
CRecordView;
• создание в классе документа объекта набор записей производного класса от класса CRecordset;
• поддержка обмена данными с таблицей RFX-методами DoFieldExchange. Рассмотрим наиболее важные фрагменты кода. Символы //{{AFX_I специально не удалены из приводимого примера, так как используются Class-Wizard.
Пример:
, class CD2Set: public CRecordset // Объявление класса набора записей { public:
CD2Set(CDatabase* pDatabase = NULL); // Конструктор набора записей
DECLARE_DYNAMIC(CD2Set) // Field/Param Data
//{{AFX_FIELD(CD2Set, CRecordset)
CString m_CITY; // Переменные для связи с полем данных CITY
CString m_FIRSTNAME; // и полем данных FIRSTNAME
//}}AFX_FIELD
// ClassWizard автоматически создает
//эти переопределяемые виртуальные методы
//{{AFX_VIRTUAL(CD2Set)
public:
virtual CString GetDefaultConnect(); // Default connection string
virtual CString GetDefaultSQL(); // default SQL for Recordset
virtual void DoFieldExchange(CFieldExchange* pFX); // RFX-поддержка
//}}AFX_VIRTUAL
CD2Set::CD2Set(CDatabase* pdb) : CRecordset(pdb) // Конструктор класса {
//{{AFX_FIELDJNIT(CD2Set)
m_CITY = _T("");
m_FIRSTNAME = _T("");
m_nFields = 2;
//}}AFX_FIELD_INIT
m_nDefaultType = snapshot; // Статический тип набора записей
// (по умолчанию) }
void CD2Set::DoFieldExchange(CFieldExchange* pFX) // Обмен данными {
//{{AFX_FIELD_MAP(CD2Set)
pFX->SetFieldType(CFieldExchange::outputColumn);
RFX_Text(pFX, _T("[CITY]"), m_CITY);
RFX_Text(pFX, _T("[FIRSTNAME]"), m_FIRSTNAME);
//}}AFX_FIELD_MAP }
class CD2View : public CRecordView // Объявление класса отображения {protected: // create from serialization only
CD2View(); // конструктор
DECLARE_DYNCREATE(CD2View) public:
//{{AFX_DATA(CD2View)
enum { IDD = IDD_D2_F0RM };
CD2Set* m_pSet; // Создание набора записей
//}}AFX_DATA public:
CD2Doc* GetDocument();
// ClassWizard автоматически создает
//эти переопределяемые виртуальные методы
//{{AFX_VIRTUAL(CD2View)
public:
virtual CRecordset* OnGetRecordset();
virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
virtual void DoDataExchange(CDataExchange* pDX); // поддержка DDX/DDV
virtual void OnInitialUpdate(); // вызывается после конструктора
//}}AFX_VIRTUAL public:
virtual ~CD2View(); protected:
// Generated message map functions protected:
//{{AFX_MSG(CD2View)
// Используется ClassWizard
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CD2View::CD2View() : CRecordView(CD2View::IDD) // Конструктор
{ //{{AFX_DATA_INIT(CD2View) mjSet = NULL; //}}AFX_DATA_INIT
}
CD2View::~CD2View() { }
void CD2View::DoDataExchange(CDataExchange* pDX) // Обмен данными
{ CRecordView::DoDataExchange(pDX); // Вызов метода базового класса //{{AFX_DATA_MAP(CD2View)
DDX_FieIdText(pDX, IDC_EDIT1, m_pSet->m_FIRSTNAME, m_pSet); DDX_FieldText(pDX, IDC_EDIT2, m_pSet->m_CITY, m_pSet); //}}AFX_DATA_MAP
>
BOOL CD2View::PreCreateWindow(CREATESTRUCT& cs)
{ return CRecordView::PreCreateWindow(cs); }
void CD2View::OnInitialUpdate()
{ m_pSet = &GetDocument()->m_d2Set; CRecordView::QnInitialUpdate();
GetParentFrame()->RecalcLayout(); ResizeParentToFit(); }
CRecordset* CD2View::OnGetRecordset() { return m_pSet; }
Создание проекта Database Project
Одним из типов создаваемых в Visual C++ проектов является Database Project. Этот проект первоначально не содержит никаких файлов кода.
Этот проект очень удобно использовать для прямого доступа к источнику данных из среды проектирования.
Для создания проекта требуется только указать используемый источник данных. В окно проекта будет добавлена вкладка Data Views, содержащая список всех таблиц и запросов для указанного источника данных. На рис. 10.6 приведен общий вид окна проекта и окна запросов, отображающего данные из таблицы FoxPro.
В окне запроса, вызываемом по двойному щелчку на имени таблицы, можно просмотреть ее содержимое, выполнить SQL-оператор, создать сохраняемый запрос.

Рис. 10.6. Окно запроса для проекта Database Project
Класс CDatabase
Объект CDatabase обеспечивает средства подключения к источнику данных. Источник данных - это набор данных (база данных), управляемый некоторой СУБД (DBMS). В качестве СУБД могут выступать Microsoft SQL Server, Microsoft Access, Borland dBASE, xBASE. Одновременно в приложении может использоваться несколько активных объектов CDatabase.
Для использования базы данных следует:
• создать объект CDatabase;
• установить соединение, открыв базу данных (вызвав метод CDatabase::OpenEx или CDatabase::Open);
• создать объект CRecordset для операций над подсоединенным источником данных, передав конструктору указатель на CDatabase;
• для завершения работы закрыть базу данных, вызвав метод CDatabase::Close. Это также закроет все наборы записей.
