OLE DB 데이터 원본 열거(OLE DB)

이 예제에서는 열거자 개체를 사용하여 사용 가능한 데이터 원본을 나열하는 방법을 보여 줍니다.

소비자는 ISourcesRowset::GetSourcesRowset 메서드를 호출하여 SQLOLEDB 열거자에 표시되는 데이터 원본을 나열할 수 있습니다. 이 메서드는 현재 표시되는 데이터 원본에 대한 정보의 행 집합을 반환합니다.

사용 중인 네트워크 라이브러리에 따라 적절한 도메인에서 데이터 원본이 검색됩니다. 명명된 파이프를 사용하는 경우 클라이언트가 로그온한 도메인에서 데이터 원본을 검색하고 AppleTalk를 사용하는 경우 기본 영역에서 데이터 원본을 검색하며 SPX/IPX를 사용하는 경우 바인더리에 있는 SQL Server 목록에서 데이터 원본을 검색하고 Banyan VINES를 사용하는 경우 로컬 네트워크에 있는 SQL Server에서 데이터 원본을 검색합니다. 멀티프로토콜 및 TCP/IP 소켓은 지원되지 않습니다.

서버를 끄거나 켤 때 이러한 도메인의 정보를 업데이트하는 데 몇 분이 소요될 수 있습니다.

이 예제에는 Microsoft SQL Server 예제 및 커뮤니티 프로젝트(Microsoft SQL Server Samples and Community Projects) 홈 페이지에서 다운로드할 수 있는 AdventureWorks 예제 데이터베이스가 필요합니다.

보안 정보보안 정보

가능하면 Windows 인증을 사용하십시오. Windows 인증을 사용할 수 없으면 런타임에 사용자에게 자격 증명을 입력하라는 메시지를 표시합니다. 자격 증명은 파일에 저장하지 않는 것이 좋습니다. 자격 증명을 유지하려면 Win32 crypto API를 사용하여 자격 증명을 암호화해야 합니다.

OLE DB 데이터 원본을 열거하려면

  1. ISourceRowset::GetSourcesRowset을 호출하여 원본 행 집합을 검색합니다.

  2. GetColumnInfo::IColumnInfo를 호출하여 열거자 행 집합에 대한 설명을 찾습니다.

  3. 열 정보를 사용하여 바인딩 구조를 만듭니다.

  4. IAccessor::CreateAccessor를 호출하여 행 집합 접근자를 만듭니다.

  5. IRowset::GetNextRows를 호출하여 행을 인출합니다.

  6. 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;
}