Перечисление источников данных OLE DB (OLE DB)
Применимо: SQL Server База данных SQL Azure Управляемый экземпляр SQL Azure azure Synapse Analytics Analytics Platform System (PDW)
В этом образце показано, как использовать объект перечислителя для построения списка доступных источников данных.
Для перечисления источников данных, доступных перечислителю MSOLEDBSQL, потребитель вызывает метод ISourcesRowset::GetSourcesRowset. Этот метод возвращает набор строк информации о видимых в настоящее время источниках данных.
В зависимости от используемой сетевой библиотеки проводится поиск источников данных в соответствующем домене. Для именованных каналов это домен, в который загружен клиент. Для AppleTalk это зона по умолчанию. Для SPX/IPX это список установок SQL Server, найденных в привязке. Для Banyan VINES это установки SQL Server, найденные в локальной сети. Сокеты Multiprotocol и TCP/IP не поддерживаются.
При выключении и включении сервера может потребоваться несколько минут на обновление информации об этих доменах.
Примеры кода Transact-SQL в этой статье используют AdventureWorks2022
базу данных или AdventureWorksDW2022
пример базы данных, которую можно скачать с домашней страницы примеров и проектов сообщества Microsoft SQL Server.
Внимание
По возможности используйте аутентификацию Windows. Если проверка подлинности Windows недоступна, запросите у пользователя ввод учетных данных во время выполнения. Избегайте хранения учетных данных в файле. Если необходимо сохранить учетные данные, зашифруйте их с помощью API-интерфейса шифрования Win32.
Перечисление источников данных OLE DB
Получите набор строк путем вызова метода ISourceRowset::GetSourcesRowset.
Найдите описание набора строк перечислителей путем вызова метода GetColumnInfo::IColumnInfo.
Создайте структуры привязки на основе информации о столбцах.
Создайте метод доступа к набору строк путем вызова метода IAccessor::CreateAccessor.
Выберите строки путем вызова метода IRowset::GetNextRows.
Получите данные из копии строки, находящейся в наборе строк, путем вызова метода IRowset::GetDataи обработайте их.
Пример
Скомпилируйте с библиотекой ole32.lib и выполните следующий листинг кода C++. Это приложение подключается к экземпляру SQL Server по умолчанию компьютера. В некоторых операционных системах Windows необходимо изменить (localhost) или (local) имя экземпляра SQL Server. Чтобы подключиться к именованному экземпляру, измените в строке подключения с значение L"(local)" на L"(local)\\<имя>", где <имя> обозначает именованный экземпляр. По умолчанию SQL Server Express устанавливает в именованный экземпляр. Убедитесь в том, что переменная среды INCLUDE включает каталог, содержащий файл msoledbsql.h.
// compile with: ole32.lib
#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0250 // to include correct interfaces
#include <windows.h>
#include <stddef.h>
#include <oledb.h>
#include <oledberr.h>
#include <msoledbsql.h>
#include <stdio.h>
#define NUMROWS_CHUNK 5
// AdjustLen supports binding on four-byte boundaries.
_inline DBLENGTH AdjustLen(DBLENGTH cb) {
return ( (cb + 3) & ~3 );
}
// Get the characteristics of the rowset (the IColumnsInfo interface).
HRESULT GetColumnInfo ( IRowset* pIRowset,
DBORDINAL* pnCols,
DBCOLUMNINFO** ppColumnsInfo,
OLECHAR** ppColumnStrings ) {
IColumnsInfo* pIColumnsInfo;
HRESULT hr;
*pnCols = 0;
if (FAILED(pIRowset->QueryInterface(IID_IColumnsInfo, (void**) &pIColumnsInfo)))
return (E_FAIL);
hr = pIColumnsInfo->GetColumnInfo(pnCols, ppColumnsInfo, ppColumnStrings);
if (FAILED(hr)) {} /* Process error */
pIColumnsInfo->Release();
return (hr);
}
// Create binding structures from column information. Binding structures
// will be used to create an accessor that allows row value retrieval.
void CreateDBBindings ( DBORDINAL nCols,
DBCOLUMNINFO* pColumnsInfo,
DBBINDING** ppDBBindings,
BYTE** ppRowValues ) {
ULONG nCol;
DBLENGTH cbRow = 0;
DBLENGTH cbCol;
DBBINDING* pDBBindings;
BYTE* pRowValues;
pDBBindings = new DBBINDING[nCols];
if (!(pDBBindings /* = new DBBINDING[nCols] */ ))
return;
for ( nCol = 0 ; nCol < nCols ; nCol++ ) {
pDBBindings[nCol].iOrdinal = nCol + 1;
pDBBindings[nCol].pTypeInfo = NULL;
pDBBindings[nCol].pObject = NULL;
pDBBindings[nCol].pBindExt = NULL;
pDBBindings[nCol].dwPart = DBPART_VALUE;
pDBBindings[nCol].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
pDBBindings[nCol].eParamIO = DBPARAMIO_NOTPARAM;
pDBBindings[nCol].dwFlags = 0;
pDBBindings[nCol].wType = pColumnsInfo[nCol].wType;
pDBBindings[nCol].bPrecision = pColumnsInfo[nCol].bPrecision;
pDBBindings[nCol].bScale = pColumnsInfo[nCol].bScale;
cbCol = pColumnsInfo[nCol].ulColumnSize;
switch (pColumnsInfo[nCol].wType) {
case DBTYPE_STR: {
cbCol += 1;
break;
}
case DBTYPE_WSTR: {
cbCol = (cbCol + 1) * sizeof(WCHAR);
break;
}
default:
break;
}
pDBBindings[nCol].obValue = cbRow;
pDBBindings[nCol].cbMaxLen = cbCol;
cbRow += AdjustLen(cbCol);
}
pRowValues = new BYTE[cbRow];
*ppDBBindings = pDBBindings;
*ppRowValues = pRowValues;
}
int main() {
ISourcesRowset* pISourceRowset = NULL;
IRowset* pIRowset = NULL;
IAccessor* pIAccessor = NULL;
DBBINDING* pDBBindings = NULL;
HROW* pRows = new HROW[500];
HACCESSOR hAccessorRetrieve = NULL;
ULONG DSSeqNumber = 0;
HRESULT hr;
DBORDINAL nCols;
DBCOLUMNINFO* pColumnsInfo = NULL;
OLECHAR* pColumnStrings = NULL;
DBBINDSTATUS* pDBBindStatus = NULL;
BYTE* pRowValues = NULL;
DBCOUNTITEM cRowsObtained;
ULONG iRow;
char* pMultiByte = NULL;
short* psSourceType = NULL;
BYTE* pDatasource = NULL;
if (!pRows)
return (0);
// Initialize COM library.
CoInitialize(NULL);
// Initialize the enumerator.
if (FAILED(CoCreateInstance(CLSID_MSOLEDBSQL_ENUMERATOR,
NULL,
CLSCTX_INPROC_SERVER,
IID_ISourcesRowset,
(void**)&pISourceRowset))) {
// Process error.
return TRUE;
}
// Retrieve the source rowset.
hr = pISourceRowset->GetSourcesRowset(NULL, IID_IRowset, 0, NULL, (IUnknown**)&pIRowset);
pISourceRowset->Release();
if (FAILED(hr)) {
// Process error.
return TRUE;
}
// Get the description of the enumerator's rowset.
if (FAILED(hr = GetColumnInfo(pIRowset, &nCols, &pColumnsInfo, &pColumnStrings))) {
// Process error.
goto SAFE_EXIT;
}
// Create the binding structures.
CreateDBBindings(nCols, pColumnsInfo, &pDBBindings, &pRowValues);
pDBBindStatus = new DBBINDSTATUS[nCols];
if (sizeof(TCHAR) != sizeof(WCHAR))
pMultiByte = new char[pDBBindings[0].cbMaxLen];
if (FAILED(pIRowset->QueryInterface(IID_IAccessor, (void**)&pIAccessor))) {
// Process error.
goto SAFE_EXIT;
}
// Create the rowset accessor.
if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA,
nCols,
pDBBindings,
0,
&hAccessorRetrieve,
pDBBindStatus))) {
// Process error.
goto SAFE_EXIT;
}
// Process all the rows, NUMROWS_CHUNK rows at a time.
while (SUCCEEDED(hr)) {
hr = pIRowset->GetNextRows(NULL, 0, NUMROWS_CHUNK, &cRowsObtained, &pRows);
if( FAILED(hr)) {
// process error
}
if (cRowsObtained == 0 || FAILED(hr))
break;
for (iRow = 0 ; iRow < cRowsObtained ; iRow++) {
// Get the rowset data.
if (SUCCEEDED(hr = pIRowset->GetData(pRows[iRow], hAccessorRetrieve, pRowValues))) {
psSourceType = (short *)(pRowValues + pDBBindings[3].obValue);
if (*psSourceType == DBSOURCETYPE_DATASOURCE) {
DSSeqNumber = DSSeqNumber + 1; // Data source counter.
pDatasource = (pRowValues + pDBBindings[0].obValue);
if ( sizeof(TCHAR) != sizeof(WCHAR) ) {
WideCharToMultiByte(CP_ACP,
0,
(WCHAR*)pDatasource,
-1,
pMultiByte,
static_cast<int>(pDBBindings[0].cbMaxLen),
NULL,
NULL);
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber,
(WCHAR *) pMultiByte );
}
else {
printf( "DataSource# %d\tName: %S\n",
DSSeqNumber,
(WCHAR *) pDatasource );
}
}
}
}
pIRowset->ReleaseRows(cRowsObtained, pRows, NULL, NULL, NULL);
}
// Release COM library.
CoUninitialize();
SAFE_EXIT:
// Do the clean-up.
return TRUE;
}