Стоит Windows 8 Pro, Visual Studio 2010 Express Edition . |
Опубликован: 17.08.2010 | Доступ: свободный | Студентов: 998 / 59 | Оценка: 4.11 / 3.89 | Длительность: 29:38:00
Тема: Программирование
Специальности: Программист, Архитектор программного обеспечения
Теги:
Самостоятельная работа 10:
Поддержка баз данных с помощью API ODBC
Код инициализации ODBC и взаимодействие с базой данных
Разработаем код, который получает данные из базы данных и заполняет ими список. Код упакуем в функцию FillDbToListBox().
-
Добавьте в класс CAPI_ODBCDlg объявление функции
Добавление в файл API_ODBCDlg.h class CAPI_ODBCDlg : public CDialog { ................................................ public: // Переменная управления списком CListBox m_ListBox; // Переменная поля ввода № п/п int m_NumEdit; // Переменная поля ввода ФИО CString m_NameEdit; // Переменная поля ввода Год int m_YearEdit; // Функция заполнения списка данными DB void FillDbToListBox(void); };
Добавление в файл API_ODBCDlg.cpp // Функция заполнения списка данными DB void CAPI_ODBCDlg::FillDbToListBox(void) { }
-
Добавьте в начало файла API_ODBCDlg.cpp следующее определение структуры
Добавление структуры в файл API_ODBCDlg.cpp // API_ODBCDlg.cpp : implementation file // #include "stdafx.h" #include "API_ODBC.h" #include "API_ODBCDlg.h" #include ".\api_odbcdlg.h" #ifdef _DEBUG #define new DEBUG_NEW #endif struct RECORD { int recNumEdit;// Переменная поля ввода № п/п CString recNameEdit;// Переменная поля ввода ФИО int recYearEdit;// Переменная поля ввода Год }; .......................................................
-
Добавьте после определения структуры RECORD следующую директиву препроцессора
Добавление директивы препроцессора в файл API_ODBCDlg.cpp ...................................................... struct RECORD { int recNumEdit;// Переменная поля ввода № п/п CString recNameEdit;// Переменная поля ввода ФИО int recYearEdit;// Переменная поля ввода Год }; #define LEN_BUF 31 // Длина буфера .......................................................
-
Найдите функцию OnInitDialog(), сгенерированную мастером, и непосредственно перед оператором return добавьте вызов функции FillDbToListBox(). Эта функция заполнит список на последнем этапе инициализации диалогового окна
Добавление вызова в файл API_ODBCDlg.cpp BOOL CAPI_ODBCDlg::OnInitDialog() { CDialog::OnInitDialog(); ............................................................. // TODO: Add extra initialization here FillDbToListBox(); return TRUE; // return TRUE unless you set the focus to a control }
-
Наполните функцию FillDbToListBox() следующим кодом, реализующим то, о чем было сказано выше
Функция FillDbToListBox() в файле API_ODBCDlg.cpp // Функция заполнения списка данными DB void CAPI_ODBCDlg::FillDbToListBox(void) { // Объявления дескрипторов и вспомогательных переменных SQLHENV henv = NULL; SQLHDBC hdbc = NULL; SQLHSTMT hstmt = NULL; bool bIsConnected = false; SQLRETURN rc; // Инициализация механизма ODBC среды rc = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv); if(rc != SQL_SUCCESS){ MessageBox("Не могу инициализировать ODBC", "", MB_OK | MB_ICONSTOP); return; } // Выбор версии ODBC-3 rc = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER); if(rc != SQL_SUCCESS){ MessageBox("Не могу установить версию ODBC", "", MB_OK | MB_ICONSTOP); return; } // Получить от ODBC дескриптор подключения к базе данных rc = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc); if(rc != SQL_SUCCESS){ MessageBox("Не могу получить дескриптор подключения к БД", "", MB_OK | MB_ICONSTOP); return; } // Подключить приложение к источнику данных rc = SQLConnect(hdbc, // Дескриптор подключения (SQLCHAR*) "MyBase", SQL_NTS, // DSN (SQLCHAR*) "", SQL_NTS, // Идентификатор пользователя (SQLCHAR*) "", SQL_NTS); // Пароль для подключения if(rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO){ MessageBox("Не могу подключиться к источнику данных", "", MB_OK | MB_ICONSTOP); return; } bIsConnected = true; // Подняли флаг, что соединение существует // Получить дескриптор оператора (statement handle) // для возможности передачи SQL-запросов rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt); if(rc != SQL_SUCCESS){ MessageBox("Не могу получить дескриптор оператора", "", MB_OK | MB_ICONSTOP); return; } // Подготовить и выполнить SQL-запрос (имя таблицы можно без расширения) LPCSTR szSQL = "SELECT number, name, birth FROM MyTable.dbf"; rc = SQLExecDirect(hstmt, (unsigned char*)szSQL, SQL_NTS); if(rc != SQL_SUCCESS){ MessageBox("Не могу выполнить SQL-запрос к БД", "", MB_OK | MB_ICONSTOP); return; } // Связывание полей с переменными приложения long int cb; // Вспомогательная типа SDWORD int iNumber; char strName[LEN_BUF]; int iBirth; SQLBindCol(hstmt, 1, SQL_INTEGER, &iNumber, 0, &cb);// Field1 SQLBindCol(hstmt, 2, SQL_CHAR, strName, LEN_BUF, &cb);// Field2 SQLBindCol(hstmt, 3, SQL_INTEGER, &iBirth, 0, &cb);// Field3 // Заполнение списка rc = SQLFetch(hstmt); while(rc == SQL_SUCCESS){ RECORD* pRecord = new RECORD; pRecord->recNumEdit = iNumber; pRecord->recNameEdit = strName; pRecord->recYearEdit = iBirth; CString strTerm; strTerm.Format("%d %s %d", iNumber, strName, iBirth); int iIndex = m_ListBox.AddString(strTerm);// Добавить в список // Сохранить указатель на неименованный экземпляр структуры в списке m_ListBox.SetItemData(iIndex, (DWORD_PTR)pRecord); rc = SQLFetch(hstmt); // Дать следующую запись } // Освободить все ресурсы ODBC if(henv){ if(hdbc){ if(bIsConnected){ if(hstmt){ SQLFreeHandle(SQL_HANDLE_STMT, hstmt); } SQLDisconnect(hdbc); bIsConnected = false; } SQLFreeHandle(SQL_HANDLE_DBC, hdbc); hdbc = NULL; } SQLFreeHandle(SQL_HANDLE_ENV, henv); henv = NULL; } }
После завершения работы приложения необходимо вернуть системе память, выделенную динамически под хранение экземпляров структуры RECORD.
-
В классе CAPI_ODBCDlg переопределите виртуальную функцию DestroyWindow() базового класса CDialog
и разместить в ней следующий код
Код функции DestroyWindow() в файл API_ODBCDlg.cpp BOOL CAPI_ODBCDlg::DestroyWindow() { RECORD* pRecord; int nCount = m_ListBox.GetCount(); for(int i = 0; i < nCount; i++){ pRecord = (RECORD*)m_ListBox.GetItemData(i); if(pRecord) delete pRecord; } return CDialog::DestroyWindow(); }
Установим связь между полями ввода Edit Control и списком List Box, добавив обработчик в класс CAPI_ODBCDlg. Для этого:
- В панели Class View выделите класс CAPI_ODBCDlg и в панели Properties включите режим Events
-
Добавьте обработчик для сообщения LBN_SELCHANGE, который заполните таким кодом
Код обработчика для списка в файле API_ODBCDlg.cpp void CAPI_ODBCDlg::OnLbnSelchangeListbox() { int iIndex = m_ListBox.GetCurSel(); if(iIndex == LB_ERR) return; RECORD* pRecord = (RECORD*)m_ListBox.GetItemData(iIndex); if(pRecord){ m_NumEdit = pRecord->recNumEdit; m_NameEdit = pRecord->recNameEdit; m_YearEdit = pRecord->recYearEdit; UpdateData(FALSE); } }
-
Добавьте в функцию OnInitDialog() класса CAPI_ODBCDlg после вызова функции FillDbToListBox() заполнение полей ввода значениями первой записи
Инициализация полей ввода в файле API_ODBCDlg.cpp BOOL CAPI_ODBCDlg::OnInitDialog() { ............................................... // TODO: Add extra initialization here FillDbToListBox(); m_ListBox.SetCurSel(0); OnLbnSelchangeListbox(); return TRUE; // return TRUE unless you set the focus to a control }
- Оформите About со своими фамилиями и номером лабораторной работы
- Постройте приложение и проверьте его работу. Результат должен быть примерно таким