На этом шаге мы рассмотрим реализация методов интерфейса 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.