列舉 OLE DB 資料來源 (OLE DB)Enumerate OLE DB Data Sources (OLE DB)

適用於: 是SQL Server是Azure SQL Database是Azure Synapse Analytics (SQL DW)是平行處理資料倉儲APPLIES TO: YesSQL Server YesAzure SQL Database YesAzure Synapse Analytics (SQL DW) YesParallel Data Warehouse

下載下載 OLE DB 驅動程式DownloadDownload OLE DB Driver

此範例會示範如何使用列舉值物件來列出可用的資料來源。This sample shows how to use the enumerator object to list the data sources available.

若要列出對 MSOLEDBSQL 列舉值而言可見的資料來源,取用者會呼叫 ISourcesRowset::GetSourcesRowset 方法。To list the data sources visible to the MSOLEDBSQL enumerator, the consumer calls the ISourcesRowset::GetSourcesRowset method. 這個方法會傳回有關目前可見之資料來源的資訊資料列集。This method returns a rowset of information about the currently visible data sources.

根據所使用的網路程式庫而定,將會搜尋適當的網域來找出資料來源。Depending on the network library used, the appropriate domain is searched for the data sources. 如果是具名管道,這就是用戶端登入的網域。For named pipes, it is the domain to which the client is logged on. 如果是 AppleTalk,這就是預設區域。For AppleTalk, it is the default zone. 如果是 SPX/IPX,這就是連結中找到的 SQL ServerSQL Server 安裝清單。For SPX/IPX, it is the list of SQL ServerSQL Server installations found in the bindery. 如果是 Banyan VINES,這就是本機網路上找到的 SQL ServerSQL Server 安裝。For Banyan VINES, it is the SQL ServerSQL Server installations found on the local network. 不支援多重通訊協定和 TCP/IP 通訊端。Multiprotocol and TCP/IP sockets are not supported.

當伺服器關閉或開啟時,可能會花上好幾分鐘的時間來更新這些網域中的資訊。When the server is turned off or on, it can take few minutes to update the information in these domains.

此範例需要 AdventureWorks 範例資料庫,您可以從 Microsoft SQL Server Samples and Community Projects (Microsoft SQL Server 範例和社群專案首頁) 下載。This sample requires the AdventureWorks sample database, which you can download from the Microsoft SQL Server Samples and Community Projects home page.

重要

盡可能使用 Windows 驗證。When possible, use Windows Authentication. 如果無法使用 Windows 驗證,請提示使用者在執行階段輸入認證。If Windows Authentication is not available, prompt users to enter their credentials at run time. 請避免將認證儲存在檔案中。Avoid storing credentials in a file. 如果您必須保存認證,則應該用 Win32 crypto API 加密這些認證。If you must persist credentials, you should encrypt them with the Win32 crypto API.

若要列舉 OLE DB 資料來源To enumerate OLE DB data sources

  1. 呼叫 ISourceRowset::GetSourcesRowset 來擷取來源資料列集。Retrieve the source rowset by calling ISourceRowset::GetSourcesRowset.

  2. 呼叫 GetColumnInfo::IColumnInfo 來尋找列舉程式資料列集的描述。Find the description of the enumerators rowset by calling GetColumnInfo::IColumnInfo.

  3. 從資料行資訊建立繫結結構。Create the binding structures from the column information.

  4. 呼叫 IAccessor::CreateAccessor 來建立資料列集存取子。Create the rowset accessor by calling IAccessor::CreateAccessor.

  5. 呼叫 IRowset::GetNextRows 來擷取資料列。Fetch the rows by calling IRowset::GetNextRows.

  6. 呼叫 IRowset::GetData 來從資料列集的資料列複本擷取資料,然後加以處理。Retrieve data from the rowset's copy of the row by calling IRowset::GetData, and process it.

範例Example

使用 ole32.lib 編譯並執行下列 C++ 程式碼清單。Compile with ole32.lib and execute the following C++ code listing. 這個應用程式會連接到電腦的預設 SQL ServerSQL Server 執行個體。This application connects to your computer's default SQL ServerSQL Server instance. 在某些 Windows 作業系統上,您必須將 (localhost) 或 (local) 變更為 SQL ServerSQL Server 執行個體的名稱。On some Windows operating systems, you will need to change (localhost) or (local) to the name of your SQL ServerSQL Server instance. 若要連線到具名執行個體,請將連接字串從 L"(local)" 變更為 L"(local)\\name",其中 name 是具名執行個體。To connect to a named instance, change the connection string from L"(local)" to L"(local)\\name" , where name is the named instance. 根據預設,SQL ServerSQL Server Express 會安裝至具名執行個體。By default, SQL ServerSQL Server Express installs to a named instance. 請確認您的 INCLUDE 環境變數包含的目錄內含 msoledbsql.h。Make sure your INCLUDE environment variable includes the directory that contains 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;  
}