Enumerar fontes de dados OLE DB (OLE DB)
Este exemplo mostra como usar o objeto enumerador para listar as fontes de dados disponíveis.
Para listar as fontes de dados visíveis para o enumerador SQLOLEDB, o consumidor chama o método ISourcesRowset::GetSourcesRowset . Esse método retorna um conjunto de linhas de informações sobre as fontes de dados visíveis no momento.
Dependendo da biblioteca de rede usada, o domínio apropriado é pesquisado em busca das fontes de dados. Para pipes nomeados, é o domínio no qual o cliente fez logon. Para AppleTalk, é a zona padrão. Para SPX/IPX, é a lista de instalações do SQL Server encontradas no bindery. Para Banyan VINES, são as instalações do SQL Server encontradas na rede local. Soquetes TCP/IP e de protocolos múltiplos não são suportados.
Quando o servidor é desativado ou ativado, pode levar alguns minutos para atualizar as informações nesses domínios.
Este exemplo exige o banco de dados de exemplo AdventureWorks, que pode ser baixado na home page de Microsoft SQL Server Samples and Community Projects (em inglês).
Importante
Quando possível, use a Autenticação do Windows. Se a Autenticação do Windows não estiver disponível, solicite aos usuários que digitem suas credenciais em tempo de execução. Evite armazenar as credenciais em um arquivo. Se for necessário manter as credenciais, criptografe-as com a Win32 crypto API(em inglês).
Para enumerar fontes de dados OLE DB
Recupere o conjunto de linhas de origem chamando
ISourceRowset::GetSourcesRowset
.Encontre a descrição do conjunto de linhas de enumeradores chamando
GetColumnInfo::IColumnInfo
.Crie as estruturas de associação a partir das informações de coluna.
Crie o acessador de conjunto de linhas chamando
IAccessor::CreateAccessor
.Busque as linhas chamando
IRowset::GetNextRows
.Recupere os dados da cópia da linha do conjunto de linhas chamando
IRowset::GetData
e processe-os.
Exemplo
Compile com ole32.lib e execute a seguinte listagem de código C++. Esse aplicativo se conecta à instância padrão do SQL Server do computador. Em alguns sistemas operacionais Windows, será necessário alterar (localhost) ou (local) para o nome de sua instância do SQL Server . Para conectar-se a uma instância nomeada, altere a cadeia de conexão de L"(local)" para L"(local)\\name", onde name é a instância nomeada. Por padrão, o SQL Server Express é instalado em uma instância nomeada. Verifique se a variável de ambiente INCLUDE inclui o diretório que contém sqlncli.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 <sqlncli.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_SQLNCLI11_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;
}