Сообщений 1 Оценка 85 Оценить |
Исходный текст примера - 10 KB
Значения полей ADO Recordset-а можно читать и записывать через объекты Field. Однако, в этом случае, приходится работать с преобразованиями из/в тип VARIANT. Альтернативой вызова методов GetFields()->GetItem(long(0)) для доступа к объектам ADO Field, GetValue() и PutValue() для чтения и записи, может служить интерфейс IADORecordBinding, предназначенный для связывания полей ADO Recordset-а с переменными C++.
IADORecordBinding – расширение ADO для Visual C++. Подробное описание можно найти в MSDN (по «указателю» IADORecordBinding). Краткое описание IADORecordBinding с примером использования будет приведено ниже.
Создаете класс, который будет включать переменные, соответствующие полям Recordset-а. Класс должен быть наследован от CADORecordBinding. Добавьте #include "icrsint.h" в ваш .h файл. Для каждого поля добавьте в класс по 2 переменные, первая типа соответствующего полю, вторая типа ULONG (переменная статуса). По переменной статуса можно узнать корректность значения первой переменной, ее использование не обязательно. Соответствие переменных полям указывается с помощью набора макросов:
Макрос |
---|
ADO_FIXED_LENGTH_ENTRY(<номер поля>, <тип данных>, <переменная>, <переменная статуса>, <возможность изменения>) |
ADO_NUMERIC_ENTRY(<номер поля>, <тип данных>, <переменная>, <количество знаков>,<количество десятичных знаков>,<переменная статуса>, <возможность изменения>) |
ADO_VARIABLE_LENGTH_ENTRY(<номер поля>, <тип данных>, <переменная>, <максимальный размер буфера>, <переменная статуса>, <реальная длина>, <возможность изменения>) |
ADO_VARIABLE_LENGTH_ENTRY2(<номер поля>, <тип данных>, <переменная>, <максимальный размер буфера>, <переменная статуса>, <возможность изменения>) |
или, если не без переменной статуса: ADO_FIXED_LENGTH_ENTRY2(<номер поля>, <тип данных>, <переменная>, <возможность изменения>) |
ADO_NUMERIC_ENTRY2(<номер поля>, <тип данных>, <переменная>, <количество знаков>,<количество десятичных знаков>, <возможность изменения>) |
ADO_VARIABLE_LENGTH_ENTRY3(<номер поля>, <тип данных>, <переменная>, <максимальный размер буфера>, <реальная длина>, <возможность изменения>) |
ADO_VARIABLE_LENGTH_ENTRY4(<номер поля>, <тип данных>, <переменная>, <максимальный размер буфера>, <возможность изменения>) |
номер поля | номер поля в Recordset-е (Не zero based, начиная с 1) |
---|---|
тип данных | ADO DataTypeEnum |
переменная | имя переменной |
переменная статуса | имя переменной статуса |
возможность изменения | TRUE – переменная, возможно, будет изменяться; FALSE – переменная не будет изменяться |
Таким образом, после определения переменных в классе, необходимо добавить в h-файл вашего класса набор описанных макросов, заключив их в пару:
BEGIN_ADO_BINDING(<имя класса>)
// Макросы связи данных
END_ADO_BINDING() |
Для подключения полученного класса к Recordset-у нужно получить интерфейс IADORecordBinding и вызвать его метод BindToRecordset с созданным классом в качестве параметра. Указатель на интерфейс можно получить через QueryInterface у Recordset-а и объявив интеллектуальный указатель с параметром Recordset.
Применим IADORecordBinding для просмотра содержимого таблицы, точнее трех ее колонок типа int, varchar и float (MS SQL Server). В примере таблица создана на сервере NONAME (MS SQL Server 7.0) в базе данных UseADOBindinding. SQL script для создания:
CREATE TABLE [dbo].[TABLE1] ( [ID] [int] IDENTITY (1, 1) NOT NULL , [Title] [varchar] (50) NULL , [Data1] [float] NULL ) ON [PRIMARY] |
h-файл класса с переменными соответствующими полям Recordset-а будет выглядеть следующим образом:
// MyRecordset.h: interface for the CMyRecordset class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_MYRECORDSET_H__75DD2CD6_0AEE_49B6_B0AA_A880F81668C7__INCLUDED_) #define AFX_MYRECORDSET_H__75DD2CD6_0AEE_49B6_B0AA_A880F81668C7__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 #include "icrsint.h" using namespace ADODB;//необходимо для макросов AD_BINDING class CMyRecordset : public CADORecordBinding { BEGIN_ADO_BINDING(CMyRecordset) ADO_FIXED_LENGTH_ENTRY(1, adInteger, m_iID, m_ulIDStatus, false) ADO_VARIABLE_LENGTH_ENTRY(2, adVarChar, m_chTitle, sizeof(m_chTitle), m_ulTitleStatus, m_iLen, false) ADO_FIXED_LENGTH_ENTRY(3, adDouble, m_dData1, m_ulData1Status, false) END_ADO_BINDING() public: CHAR m_chTitle[51]; double m_dData1; long m_iID; DWORD m_iLen; // переменные статуса ULONG m_ulIDStatus; ULONG m_ulTitleStatus; ULONG m_ulData1Status; CMyRecordset(); virtual ~CMyRecordset(); }; #endif // !defined(AFX_MYRECORDSET_H__75DD2CD6_0AEE_49B6_B0AA_A880F81668C7__INCLUDED_) |
Импорт ADO сделаем в stdafx.h файле
#import "C:\Program Files\Common Files\system\ado\msado21.tlb" rename("EOF","ADOEOF") rename("BOF","ADOBOF") |
Собственно программа
// HowToBind.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <icrsint.h> #include <stdio.h> #include "MyRecordset.h" _COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding)); int main(int argc, char* argv[]) { CoInitialize(NULL); ADODB::_RecordsetPtr pRset("ADODB.Recordset"); CMyRecordset rs; try { IADORecordBindingPtr picRs(pRset); pRset->Open("SELECT ID, Title, Data1 FROM Table1", "Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa;Initial Catalog=UseADOBinding;Data Source=NONAME", ADODB::adOpenStatic, ADODB::adLockOptimistic, ADODB::adCmdText); picRs->BindToRecordset(&rs); pRset->MoveFirst(); while(!pRset->ADOEOF) { printf("%d %s %f\n", (rs.m_ulIDStatus==adFldOK ? rs.m_iID: 0), (rs.m_ulTitleStatus==adFldOK ? rs.m_chTitle : ""), (rs.m_ulData1Status==adFldOK ? rs.m_dData1 : 0)); pRset->MoveNext(); } } catch(_com_error&) {} CoUninitialize(); return 0; } |
На CodeGuru есть интересная утилита создающая h-файлы для класса Recordset-а. Она предлагает выбрать источник данных и таблицу. Для сложных запросов она не подходит, однако можно сделать заготовку и потом ее отредактировать.
Сообщений 1 Оценка 85 Оценить |