На этом шаге мы рассмотрим реализация методов интерфейса IUploadStockData.
Сейчас вернемся к проекту STLoadData; мы напишем код методов ConnectToDatabase(), Disconnect() и UploadRecord() интерфейса IUploadStockData, предоставляемого компонентом UploadStockData.
Сначала нужно импортировать библиотеку типов ADO, чтобы в проекте стали доступны определения GUID, а также создать "интеллектуальные" указатели на интерфейсы ADO.
#import "C:\Program Files\Common Files\System\ado\msado15.dll" \ no_namespace rename("EOF", "adoEOF")
Рис.1. Размещение строки
Компилятор обработает директиву #import в файле StdAfx.h и создаст в папке Debug файлы msadol5.tlh и msadol5.tli. Они содержат определения GUID и объявления "интеллектуальных" указателей на интерфейсы ADO, которые теперь стали доступными в проекте STLoadData.
Компонент UploadStockData подключается к базе данных через отдельный ADO-объект Connection, который используется последовательными вызовами метода UploadRecord(). Этот объект реализуется как переменная-член класса компонента и открывается/закрывается методами ConnectToDatabase() и Disconnect() соответственно.
_ConnectionPtr m_pConnection;
m_pConnection = NULL;
Рис.2. Добавление защищенного элемента данных
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; }
STDMETHODIMP CUploadStockData::Disconnect() { if(m_pConnection) { m_pConnection->Close(); m_pConnection = NULL; } return S_OK; }
Рис.3. Установка указанных параметров
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() вызывается для загрузки новой записи в базу данных.
На следующем шаге мы рассмотрим реализацию команды Upload Data.