Differences between revisions 1 and 2

Deletions are marked like this. Additions are marked like this.
Line 17: Line 17:
{{{#!sql  {{{#!sql numbers=off
Line 36: Line 36:
{{{#!sql  {{{#!sql numbers=off
Line 92: Line 92:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 101: Line 101:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 312: Line 312:
== OLE DB 소비자 특성 ==

OLE DB Consumer Attributes -
The OLE DB consumer attributes inject code, based on the OLE DB Consumer Templates, to create a working OLE DB consumer that performs tasks such as opening tables, executing commands, and accessing data.

 ||<rowclass="THEAD"> 특성 || 설명 ||
 || db_accessor || Binds columns in a rowset and binds them to the corresponding accessor maps. ||
 || db_column || Binds a specified column to the rowset. ||
 || db_command || Executes an OLE DB command. ||
 || db_param || Associates the specified member variable with an input or output parameter. ||
 || db_source || Creates and encapsulates a connection, through a provider, to a data source. ||
 || db_table || Opens an OLE DB table. ||

=== OLE DB 소비자 특성을 이용한 프로그래밍 ===

 * CUserInfo 테이블 쿼리 클래스 선언
 {{{#!cplusplus numbers=off
// UserInfo.h : CUserInfo 클래스 선언
//

#pragma once

[
 db_table( L"dbo.UserInfo" )
]

class CUserInfo
{
public:
 [ db_column(1) ] LONG m_ID;
 [ db_column(2) ] TCHAR m_Name[21];
 [ db_column(3) ] SHORT m_Age;
 [ db_column(4) ] TCHAR m_Phone[14];
};
}}}

 * 프로그래밍 과정
 {{{#!cplusplus numbers=on
// ATL OLE DB 소비자 템플릿 라이브러리 헤더 파일
#include <atldbcli.h>

//------------------------------------------------------------------------------
// STEP 1: COM 초기화
HRESULT hr = CoInitialize( NULL );
if( FAILED( hr ) )
{
 // ERROR: COM 초기화 실패
 // 에러 처리
}

//------------------------------------------------------------------------------
// STEP 2: 데이터베이스 연결
CDataConnection dbConn;

WCHAR szDbStr[ 256 ];
swprintf( szDbStr, L"Provider=SQLOLEDB.1;Data Source=%s;User ID=%s;Password=%s&;Initial Catalog=%s;",
 SERVER_STR, // 서버 정보 (주소,포트)
 UID_STR, // 로그인 정보 (사용자 ID)
 PWD_STR, // 암호
 DATABASE_STR ); // DB 이름

hr = dbConn.Open( szDbStr );
if( FAILED( hr ) )
{
 // ERROR: 데이터베이스 연결 실패
 // 에러 처리
}

//------------------------------------------------------------------------------
// STEP 3: 쿼리 실행
CUserInfo tblUserInfo;

hr = tblUserInfo.OpenRowset( dbConn.m_session );
if( FAILED( hr ) )
{
 // ERROR: 쿼리 실행 실패
 // 에러 처리
}

while( S_OK == tblUserInfo.MoveNext() )
{
 printf( "ID\t: %d\n", tblUserInfo.m_ID );
 printf( "Name\t: %s\n", tblUserInfo.m_Name );
 printf( "Age\t: %d\n", tblUserInfo.m_Age );
 printf( "Phone\t: %s\n", tblUserInfo.Phone );
}

//------------------------------------------------------------------------------
// STEP 4: 쿼리 해제 & 데이터베이스 연결 닫기
tblUserInfo.Close();
dbConn.CloseDataSource();

// STEP 5: COM 해제
CoUninitialize();
}}}

Line 342: Line 439:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 351: Line 448:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 360: Line 457:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 369: Line 466:
 {{{#!cplusplus  {{{#!cplusplus numbers=off
Line 378: Line 475:
 {{{#!cplusplus  {{{#!cplusplus numbers=off

OLE DB 프로그래밍은 COM 구조를 사용하기 때문에 COM 프로그래밍에 대한 이해가 필요하다. 하지만 ATL 의 OLE DB 템플릿 라이브러리를 이용하면 손쉽게 OLE DB 프로그래밍이 가능하다. 따라서 다음은 ATL OLE DB 템플릿 라이브러리를 이용하여 프로그래밍하는 과정을 정리해 본다.

1. 준비 작업 [Bottom] [Top]

OLE DB 프로그래밍에 앞서 사용될 DB 테이블과 저장 프로시저를 생성한다. 각 테이블의 데이터는 임의적으로 생성하여 저장한다.

1.1. DB 테이블 생성 [Bottom] [Top]

  • -- Account 테이블 생성 ---------------------------------------------------------
    CREATE TABLE dbo.Account (
            [UID]           INT             IDENTITY(10,1)  NOT NULL,
            [UserID]        VARCHAR(32)     NOT NULL,
            [Passwd]        VARCHAR(16)     NOT NULL
    )
    
    -- Item 테이블 생성 ------------------------------------------------------------
    CREATE TABLE dbo.Item (
            [UID]           INT             NOT NULL,
            [Col]           TINYINT         NOT NULL,
            [ItemID]        INT             NOT NULL,
            [Count]         TINYINT         NOT NULL
    )
    

1.2. 저장 프로시저 생성 [Bottom] [Top]

  • -- 사용자 인증 처리 (사용자 검색, 암호 비교) -----------------------------------
    CREATE PROCEDURE dbo.SP_LOGIN_PROC
    (
            @UserID         VARCHAR(32)
    ,       @Passwd         VARCHAR(16)
    ,       @UID            INT             OUTPUT
    )
    AS
    BEGIN
            DECLARE @strPWD VARCHAR(16)
    
            SET NOCOUNT ON
    
            SELECT TOP 1 @strPWD = [Passwd], @UID = [UID]
                    FROM dbo.Account
                    WHERE [UserID] = @UserID
    
            IF @strPWD IS NULL
              BEGIN
                    RETURN 1        -- 사용자 없음
              END
    
            IF CAST(@strPWD AS VARBINARY) <> CAST(@Passwd AS VARBINARY)
              BEGIN
                    RETURN 2        -- 암호 불일치
              END
    
            RETURN 0                -- 인증 완료
    END
    
    -- 아이템 처리 (사용자 아이템 목록) --------------------------------------------
    CREATE PROCEDURE dbo.SP_ITEM_SELECT
    (
            @UID            INT
    )
    AS
    BEGIN
            SET NOCOUNT ON
    
            SELECT Col, ItemID, [Count]
                    FROM dbo.item
                    WHERE [UID] = @UID
                    ORDER BY Col
    END
    

2. ATL OLE DB 프로그래밍 과정 [Bottom] [Top]

구현 과정에서 일반적인 쿼리문 (예: SELECT, INSERT, DELETE, UPDATE 문 등) 을 사용할 수 있으나 속도 향상이나 다양한 처리를 위하여 저장 프로시저 (Stored Procedure) 를 사용하였다.

2.1. ATL 헤더 파일 추가 [Bottom] [Top]

ATL OLE DB 소비자 템플릿 라이브러리 헤더 파일을 추가한다.

  • #include <atldbcli.h>
    
    

2.2. 랩퍼 (Wrapper) 클래스 추가 [Bottom] [Top]

  1. 저장 프로시저 실행을 위한 랩퍼 클래스 추가
    • 단순히 저장 프로시저만 실행하고 결과값만 반환 받는 랩퍼 클래스
    // QLogin.h : QLogin 쿼리 클래스 선언
    //
    
    #pragma once
    
    
    // 쿼리 클래스 선언
    class QLogin
    {
            // 매개변수 선언
    public:
            LONG    m_lResult;
            TCHAR   m_szUserID[ 33 ];
            TCHAR   m_szPasswd[ 17 ];
            LONG    m_lUID;
    
            // 쿼리문 선언
            DEFINE_COMMAND_EX( QLogin, OLESTR( "{ ? = CALL dbo.SP_LOGIN_PROC(?,?,?) }" ) )
    
            // 매개변수 맵 선언
            BEGIN_PARAM_MAP(QLogin)
                    SET_PARAM_TYPE(DBPARAMIO_OUTPUT)
                    COLUMN_ENTRY(1, m_lResult)
                    SET_PARAM_TYPE(DBPARAMIO_INPUT)
                    COLUMN_ENTRY(2, m_szUserID)
                    SET_PARAM_TYPE(DBPARAMIO_INPUT)
                    COLUMN_ENTRY(3, m_szPasswd)
                    SET_PARAM_TYPE(DBPARAMIO_INPUT | DBPARAMIO_OUTPUT)
                    COLUMN_ENTRY(4, m_lUID)
            END_PARAM_MAP()
    };
    
    
    // 데이터형 선언
    typedef CCommand< CAccessor< QLogin > >         QUERY_LOGIN;
    
  2. 쿼리를 위한 랩퍼 클래스 추가
    • 쿼리 (저장 프로시저) 를 통하여 레코드 단위로 데이터를 얻는 랩퍼 클래스
       1 // QItemList.h : QItemList 쿼리 클래스 선언
       2 //
       3 
       4 #pragma once
       5 
       6 
       7 // 쿼리 클래스 선언
       8 class QItemList
       9 {
      10         // 데이터열 선언
      11 public:
      12         BYTE    m_bCol;
      13         LONG    m_lItemID;
      14         BYTE    m_bCount;
      15 
      16         // 매개변수 선언
      17 public:
      18         LONG    m_lUID;
      19 
      20         // 쿼리문 선언
      21         DEFINE_COMMAND_EX( QItemList, OLESTR( "{ CALL dbo.SP_ITEM_SELECT(?) }" ) )
      22 
      23         // 데이터열 맵 선언
      24         BEGIN_COLUMN_MAP(QItemList)
      25                 COLUMN_ENTRY( 1, m_bCol )
      26                 COLUMN_ENTRY( 2, m_lItemID )
      27                 COLUMN_ENTRY( 3, m_bCount )
      28         END_COLUMN_MAP()
      29 
      30         // 매개변수 맵 선언
      31         BEGIN_PARAM_MAP(QItemList)
      32                 SET_PARAM_TYPE(DBPARAMIO_INPUT)
      33                 COLUMN_ENTRY(1, m_lUID)
      34         END_PARAM_MAP()
      35 };
      36 
      37 
      38 // 데이터형 선언
      39 typedef CCommand< CAccessor< QItemList > >      QUERY_ITEM_LIST;
    

2.3. COM 초기화 및 데이터베이스 / 세션 연결 과정 [Bottom] [Top]

  •    1 // STEP 1: COM 초기화
       2 HRESULT hr = CoInitialize( NULL );
       3 if( FAILED( hr ) )
       4 {
       5         // ERROR: COM 초기화 실패
       6         // 에러 처리
       7 }
       8 
       9 // STEP 2: 데이터베이스 연결
      10 //// STEP 2-1: CLSID 얻기
      11 CLSID clsid = CLSID_NULL;
      12 if( FAILED( CLSIDFromProgID( OLESTR("SQLOLEDB.1"), &clsid ) ) )
      13 {
      14         // ERROR: SQLOLEDB CLSID 얻기 실패
      15         // 에러 처리
      16 }
      17 
      18 //// STEP 2-2: 데이터베이스 연결 준비
      19 char szDBstr[ 256 ];
      20 sprintf_s( szDBstr, "Provider=SQLOLEDB.1;Server=%s;Database=%s;UID=%s;PWD=%s",
      21                 SERVER_STR,                     // 서버 정보 (주소,포트)
      22                 DATABASE_STR,                   // DB 이름
      23                 UID_STR,                        // 로그인 정보 (사용자 ID)
      24                 PWD_STR );                      // 암호
      25 
      26 CDBPropSet dbinit( DBPROPSET_DBINIT );
      27 dbinit.AddProperty( DBPROP_INIT_PROMPT, static_cast< short >( 4 ) );
      28 dbinit.AddProperty( DBPROP_INIT_PROVIDERSTRING, szDBstr );
      29 
      30 //// STEP 2-3: 데이터베이스 연결 시도
      31 CDataSource ds;
      32 
      33 hr = ds.Open( clsid, &dbinit );
      34 if( FAILED( hr ) )
      35 {
      36         // ERROR: 데이터베이스 연결 실패
      37         // 에러 처리
      38 }
      39 
      40 // STEP 3: 세션 연결
      41 CSession ss;
      42 
      43 hr = ss.Open( ds );
      44 if( FAILED( hr ) )
      45 {
      46         // ERROR: 세션 연결 실패
      47         // 에러 처리
      48 }
    

2.4. SQL 쿼리 (SQL Query) 실행 [Bottom] [Top]

  1. 저장 프로시저 실행
       1 // 쿼리 객체 정의
       2 QUERY_LOGIN login;
       3 
       4 // 쿼리 조건 설정
       5 _tcscpy_s( login.m_szUserID, USER_ID );         // USER_ID: 사용자ID
       6 _tcscpy_s( login.m_szPasswd, PASSWD );          // PASSWD : 암호
       7 
       8 // 쿼리 실행
       9 HRESULT hr = login.Open( ss );
      10 if( FAILED( hr ) )
      11 {
      12         // ERROR: 쿼리 실행 실패
      13         // 에러 처리
      14 }
      15 
      16 // 결과 처리
      17 LONG lUID = 0;
      18 if( 0 == login.m_lResult )
      19 {
      20         lUID = login.m_lUID;
      21 }
      22 
      23 printf( "Account: %s, Password: %s ==> UID: %d, Result: %d\n",
      24         USER_ID, PASSWD, lUID, login.m_lResult );
      25 
      26 // 쿼리 해제
      27 login.Close();
    
  2. 쿼리 실행
       1 // 쿼리 객체 정의
       2 QUERY_ITEM_LIST itemList;
       3 
       4 // 쿼리 조건 설정
       5 itemList.m_lUID = USER_UID;                     // USER_UID: 사용자 UID
       6 
       7 // 쿼리 실행
       8 HRESULT hr = itemList.Open( ss );
       9 if( FAILED( hr ) )
      10 {
      11         // ERROR: 쿼리 실행 실패
      12         // 에러 처리
      13 }
      14 
      15 // 결과 처리
      16 printf( ">>> Item List (UID: %d)\n", USER_UID );
      17 
      18 while( itemList.MoveNext() == S_OK )
      19 {
      20         printf( "\tCol: %d, ItemID: %d, Count: %d\n",
      21                 itemList.m_bCol, itemList.m_lItemID, itemList.m_bCount );
      22 }
      23 
      24 // 쿼리 해제
      25 itemList.Close();
    

2.5. 세션 / 데이터베이스 닫기 및 COM 해제 [Bottom] [Top]

  •    1 // STEP 1: 세션 닫기
       2 ss.Close();
       3 
       4 // STEP 2: 데이터베이스 닫기
       5 ds.Close();
       6 
       7 // STEP 3: COM 해제
       8 CoUninitialize();
    

3. OLE DB 소비자 특성 [Bottom] [Top]

OLE DB Consumer Attributes - The OLE DB consumer attributes inject code, based on the OLE DB Consumer Templates, to create a working OLE DB consumer that performs tasks such as opening tables, executing commands, and accessing data.

  • 특성

    설명

    db_accessor

    Binds columns in a rowset and binds them to the corresponding accessor maps.

    db_column

    Binds a specified column to the rowset.

    db_command

    Executes an OLE DB command.

    db_param

    Associates the specified member variable with an input or output parameter.

    db_source

    Creates and encapsulates a connection, through a provider, to a data source.

    db_table

    Opens an OLE DB table.

3.1. OLE DB 소비자 특성을 이용한 프로그래밍 [Bottom] [Top]

  • CUserInfo 테이블 쿼리 클래스 선언
    // UserInfo.h : CUserInfo 클래스 선언
    //
    
    #pragma once
    
    [
            db_table( L"dbo.UserInfo" )
    ]
    
    class CUserInfo
    {
    public:
            [ db_column(1) ] LONG   m_ID;
            [ db_column(2) ] TCHAR  m_Name[21];
            [ db_column(3) ] SHORT  m_Age;
            [ db_column(4) ] TCHAR  m_Phone[14];
    };
    
  • 프로그래밍 과정
       1 // ATL OLE DB 소비자 템플릿 라이브러리 헤더 파일
       2 #include <atldbcli.h>
       3 
       4 //------------------------------------------------------------------------------
       5 // STEP 1: COM 초기화
       6 HRESULT hr = CoInitialize( NULL );
       7 if( FAILED( hr ) )
       8 {
       9         // ERROR: COM 초기화 실패
      10         // 에러 처리
      11 }
      12 
      13 //------------------------------------------------------------------------------
      14 // STEP 2: 데이터베이스 연결
      15 CDataConnection dbConn;
      16 
      17 WCHAR szDbStr[ 256 ];
      18 swprintf( szDbStr, L"Provider=SQLOLEDB.1;Data Source=%s;User ID=%s;Password=%s&;Initial Catalog=%s;",
      19         SERVER_STR,                     // 서버 정보 (주소,포트)
      20         UID_STR,                        // 로그인 정보 (사용자 ID)
      21         PWD_STR,                        // 암호
      22         DATABASE_STR );         // DB 이름
      23 
      24 hr = dbConn.Open( szDbStr );
      25 if( FAILED( hr ) )
      26 {
      27         // ERROR: 데이터베이스 연결 실패
      28         // 에러 처리
      29 }
      30 
      31 //------------------------------------------------------------------------------
      32 // STEP 3: 쿼리 실행
      33 CUserInfo tblUserInfo;
      34 
      35 hr = tblUserInfo.OpenRowset( dbConn.m_session );
      36 if( FAILED( hr ) )
      37 {
      38         // ERROR: 쿼리 실행 실패
      39         // 에러 처리
      40 }
      41 
      42 while( S_OK == tblUserInfo.MoveNext() )
      43 {
      44         printf( "ID\t: %d\n", tblUserInfo.m_ID );
      45         printf( "Name\t: %s\n", tblUserInfo.m_Name );
      46         printf( "Age\t: %d\n", tblUserInfo.m_Age );
      47         printf( "Phone\t: %s\n", tblUserInfo.Phone );
      48 }
      49 
      50 //------------------------------------------------------------------------------
      51 // STEP 4: 쿼리 해제 & 데이터베이스 연결 닫기
      52 tblUserInfo.Close();
      53 dbConn.CloseDataSource();
      54 
      55 // STEP 5: COM 해제
      56 CoUninitialize();
    

4. ATL OLE DB 클래스 구조 [Bottom] [Top]

  • 데이터 소스 및 세션 클래스


  • 접근자 클래스


  • 행 집합 클래스


  • 명령 및 테이블 클래스

5. OLE DB Provider & CLSID 관련 정보 [Bottom] [Top]

  1. Microsoft OLE DB Provider for SQL Server

    • sqloledb.dll
    • SQLOLEDB.1
    #include <sqloledb.h>
    
    CLSID CLSID_SQLOLEDB    = {0xC7FF16CL,0x38E3,0x11D0,{0x97,0xAB,0x0,0xC0,0x4F,0xC2,0xAD,0x98}};
    
  2. Microsoft OLE DB Provider for Oracle

    • msdaora.dll
    • msdaora
    #include <msdaora.h>
    
    CLSID CLSID_MSDAORA     = {0xE8CC4CBE,0xFDFF,0x11D0,{0xB8,0x65,0x00,0xA0,0xC9,0x08,0x1C,0x1D}};
    
  3. Oracle Provider for OLE DB

    • OraOLEDB.dll
    • OraOLEDB.Oracle.1
    #include "OraOLEDB.h"
    
    CLSID CLSID_OraOLEDB    = {0x3F63C36E,0x51A3,0x11D2,{0xBB,0x7D,0x00,0xC0,0x4F,0xA3,0x00,0x80}};
    
  4. Microsoft Data Access - OLE DB Provider for ODBC Drivers

    • msdasql.dll
    • MSDASQL.1
    #include <msdasql.h>
    
    CLSID CLSID_MSDASQL     = {0xC8B522CBL,0x5CF3,0x11CE,{0xAD,0xE5,0x00,0xAA,0x00,0x44,0x77,0x3D}};
    
  5. Microsoft Data Access - OLE DB Simple Provider

    • msdaosp.dll
    • MSDAOSP.1
    #include <msdaosp.h>
    
    CLSID CLSID_MSDAOSP     = {0xDFC8BDC0,0xE378,0x11D0,{0x9B,0x30,0x0,0x80,0xC7,0xE9,0xFE,0x95}};
    


CategoryDatabase CategoryWin32

OLE DB 프로그래밍 (last edited 2009-09-10 09:07:34 by viper)