На этом шаге мы рассмотрим реализация методов интерфейса IUploadStockData.
Сейчас вернемся к проекту STLoadData; мы напишем код методов ConnectToDatabase(),
Disconnect() и UploadRecord() интерфейса IUploadStockData, предоставляемого
компонентом UploadStockData.
Сначала нужно импортировать библиотеку типов ADO, чтобы в проекте стали доступны определения GUID,
а также создать "интеллектуальные" указатели на интерфейсы ADO.
- Импорт библиотеки типов ADO.
- Откройте в Visual Studio файл рабочей области STUpload.dsw. Убедитесь, что Вам доступны все
функции панели инструментов Build и затем выберите из раскрывающегося списка проект STLoadData. - В FileView раскройте подузел Header Files узла STLoadData. Дважды щелкните файл StdAfx.h.
- В конце файла перед комментарием // {{AFX_INSERT_LOCATION}} добавьте:
#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ no_namespace rename("EOF", "adoEOF")
Рис.1. Размещение строки
На Вашем компьютере путь к файлу msadol5.dll может отличаться, поэтому проверьте его правильность. Обратите
также внимание, что в примере, показанном выше, для разделения директивы на две строки используется символ
продолжения \. - Сохраните и закройте файл StdAfx.h.
- В FileView в узле Source Files щелкните правой кнопкой мыши файл StdAfx.cpp. В открывшемся контекстном меню выберите
Compile StdAfx.cpp. - Реализация объекта Connection.
- Добавьте в определение класса CUploadStockData в файле UploadStockData.h следующий
защищенный элемент данных:_ConnectionPtr m_pConnection;
- В этом же файле добавьте в конструктор класса CUploadStockData следующую строку:
m_pConnection = NULL;
Рис.2. Добавление защищенного элемента данных - В файле UploadStockData.срр найдите функцию CUploadStockData::ConnectToDatabase() и добавьте в нее код,
чтобы она выглядела вот так:STDMETHODIMP CUploadStockData::ConnectToDatabase() { // Проверяем, нет ли подключения в настоящий момент if(m_pConnection) return S_OK; HRESULT hr =m_pConnection.CreateInstance(__uuidof(Connection)); if(FAILED(hr)) return hr; hr = m_pConnection->Open(L"File Name=G:\\DataLinks\\STLink.UDL", L"", L"", -1); if(FAILED(hr)) return hr; return S_OK; }
Как Вы помните, переменная mpConnection - это "интеллектуальный" указатель типа _com_ptr_t на
интерфейс, предоставляемый ADO-объектом Connection. - Найдите функцию CUploadStockData::Disconnect() и добавьте в нее код, чтобы она выглядела следующим образом:
STDMETHODIMP CUploadStockData::Disconnect() { if(m_pConnection) { m_pConnection->Close(); m_pConnection = NULL; } return S_OK; }
Теперь Вы подготовились к тому, чтобы написать код метода IUploadStockData::UploadRecord().
- Реализация метода UploadRecord().
- В меню Project щелкните команду Settings. Убедитесь, что в левой части окна выбран проект
STLoadData. На вкладке С/С ++ диалогового окна Project Settings в раскрывающемся списке
Category укажите C++ Language. Щелкните Enable exception handling и затем - OK.
Рис.3. Установка указанных параметров - В файле UploadStockData.cpp найдите функцию CUploadStockData::UploadRecord() и
отредактируйте ее следующим образом:STDMETHODIMP CUploadStockData::UploadRecord(BSTR fund, DATE date, double price, BSTR uplBy, DATE uplDate) { // Проверяем наличие активного соединения // с источником данных if ( m_pConnection == NULL ) return E_FAIL; // Создаем набор записей _RecordsetPtr pRecordset; HRESULT hr = pRecordset.CreateInstance(__uuidof( Recordset )); if( FAILED( hr ) ) return hr; try { // Открываем набор данных _variant_t vConnection = m_pConnection.GetInterfacePtr(); hr = pRecordset->Open( L"pricehistory", vConnection, adOpenForwardOnly, adLockOptimistic, adCmdTableDirect ); if( FAILED( hr ) ) return hr; // Добавляем новую запись, помещаем // новые значения в поля // и обновляем базу данных hr = pRecordset->AddNew(); if( FAILED( hr ) ) throw _com_error( hr ); pRecordset->Fields->GetItem( L"ph_fund")->Value = fund; pRecordset->Fields->GetItem( L"ph_date")->Value = date; pRecordset->Fields->GetItem( L"ph_price")->Value = price; pRecordset->Fields->GetItem( L"ph_uploadedby")->Value = uplBy; pRecordset->Fields->GetItem( L"ph_uploaddate")->Value = uplDate; hr = pRecordset->Update(); if( FAILED( hr ) ) throw _com_error( hr ); } catch ( _com_error e ) { // простейшая обработка исключения try { pRecordset->Close(); } catch (...) // Close() может возбудить еще одно исключение { } return E_FAIL; } pRecordset->Close(); return S_OK; }
Обратите внимание: существующий Connection-объект mpConnection передается в качестве параметра
в метод Ореn() объекта Recordset. Чтобы узнать подробности о других параметрах Ореn(),
выполните в справочной системе Visual C++ поиск по слову "ADO". Обратите также внимание,
что методы AddNew() и Update() ADO-объекта Recordset для добавления новой записи
применяются совместно. Новая запись добавляется в набор записей с помощью AddNew(), в полях (доступ
к которым осуществляется через набор Fields объекта Recordset) задаются новые значения, а метод
Update() вызывается для загрузки новой записи в базу данных. - Теперь Вы можете собрать проект STLoadData, чтобы вновь скомпилировать и перерегистрировать
СОМ-сервер STLoadData.dll.
Компилятор обработает директиву #import в файле StdAfx.h и создаст в папке Debug файлы
msadol5.tlh и msadol5.tli. Они содержат определения GUID и объявления "интеллектуальных" указателей на интерфейсы ADO,
которые теперь стали доступными в проекте STLoadData.
Компонент UploadStockData подключается к базе данных через отдельный ADO-объект Connection, который
используется последовательными вызовами метода UploadRecord(). Этот объект реализуется как
переменная-член класса компонента и открывается/закрывается методами ConnectToDatabase() и Disconnect() соответственно.
Текст измененного приложения можно взять здесь (731,0 Кб).
На следующем шаге мы рассмотрим реализацию команды Upload Data.