列舉 OLE DB 資料來源 (OLE DB)
此範例會示範如何使用列舉值物件來列出可用的資料來源。
若要列出對 SQLOLEDB 列舉值而言可見的資料來源,取用者會呼叫 ISourcesRowset::GetSourcesRowset 方法。 這個方法會傳回有關目前可見之資料來源的資訊資料列集。
根據所使用的網路程式庫而定,將會搜尋適當的網域來找出資料來源。 如果是具名管道,這就是用戶端登入的網域。 如果是 AppleTalk,這就是預設區域。 如果是 SPX/IPX,這就是連結中找到的 SQL Server 安裝清單。 如果是 Banyan VINES,這就是本機網路上找到的 SQL Server 安裝。 不支援多重通訊協定和 TCP/IP 通訊端。
當伺服器關閉或開啟時,可能會花上好幾分鐘的時間來更新這些網域中的資訊。
此範例需要 AdventureWorks 範例資料庫,您可以從 Microsoft SQL Server 範例和社群專案首頁 (英文) 下載。
安全性注意事項 |
---|
盡可能使用 Windows 驗證。 如果無法使用 Windows 驗證,請提示使用者在執行階段輸入認證。 請避免將認證儲存在檔案中。 如果您必須保存認證,則應該用 Win32 crypto API 加密這些認證。 |
若要列舉 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)\\name",其中 name 是具名執行個體。 根據預設,SQL Server Express 會安裝至具名執行個體。 請確認您的 INCLUDE 環境變數包含的目錄內含 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;
}