다음을 통해 공유


Visual C++ ADO 프로그래밍

ADO API 참조는 Microsoft Visual Basic과 유사한 구문을 사용하여 ADO API(애플리케이션 프로그래밍 인터페이스)의 기능을 설명합니다. 의도된 대상 그룹은 모두 사용자이지만 ADO 프로그래머는 Visual Basic, Visual C++(#import 지시문 포함 및 제외), Visual J++(ADO/WFC 클래스 패키지 포함)와 같은 다양한 언어를 사용합니다.

참고 항목

Microsoft는 2004년에 Visual J++에 대한 지원을 종료했습니다.

이 다양성을 수용하기 위해 ADO for Visual C++ 구문 인덱스는 API 참조에서 기능, 매개 변수, 예외적 동작 등에 대한 일반적인 설명의 링크가 포함된 Visual C++ 언어별 구문을 제공합니다.

ADO는 COM(구성 요소 개체 모델) 인터페이스를 사용하여 구현됩니다. 그러나 프로그래머는 다른 것보다 특정 프로그래밍 언어로 COM을 사용하는 것이 더 쉽습니다. 예를 들어 거의 모든 COM 사용 세부 정보는 Visual Basic 프로그래머에 대해 암시적으로 처리되는 반면, Visual C++ 프로그래머는 해당 세부 정보 자체를 처리해야 합니다.

다음 섹션에서는 ADO 및 #import 지시문을 사용하는 C 및 C++ 프로그래머에 대한 세부 정보를 요약합니다. COM(Variant, BSTR, SafeArray) 및 오류 처리(_com_error)와 관련된 데이터 형식에 중점을 둡니다.

#import 컴파일러 지시문 사용

#import Visual C++ 컴파일러 지시문은 ADO 메서드 및 속성 작업을 간소화합니다. 이 지시문은 ADO .dll(Msado15.dll)과 같은 형식 라이브러리가 포함된 파일의 이름을 사용하고 typedef 선언, 인터페이스에 대한 스마트 포인터, 열거형 상수가 포함된 헤더 파일을 생성합니다. 각 인터페이스는 클래스에서 캡슐화되거나 래핑됩니다.

클래스 내 각 작업(메서드 또는 속성 호출)의 경우 작업을 직접 호출하는 선언(작업의 “원시” 형식)과 원시 작업을 호출하고 작업이 성공적으로 실행되지 않을 경우 COM 오류를 throw하는 선언이 있습니다. 작업이 속성인 경우 일반적으로 Visual Basic과 같은 구문이 있는 작업에 대한 대체 구문을 만드는 컴파일러 지시문이 있습니다.

속성 값을 검색하는 작업에는 GetProperty 형식의 이름이 있습니다. 속성 값을 설정하는 작업에는 PutProperty 형식의 이름이 있습니다. ADO 개체에 대한 포인터를 사용하여 속성 값을 설정하는 작업에는 PutRefProperty 형식의 이름이 있습니다.

다음 형식의 호출을 사용하여 속성을 가져오거나 설정할 수 있습니다.

variable = objectPtr->GetProperty(); // get property value   
objectPtr->PutProperty(value);       // set property value  
objectPtr->PutRefProperty(&value);   // set property with object pointer  

속성 지시문 사용

__declspec(property...) 컴파일러 지시문은 대체 구문을 포함하기 위해 속성으로 사용되는 함수를 선언하는 Microsoft 관련 C 언어 확장입니다. 따라서 Visual Basic과 비슷한 방식으로 속성 값을 설정하거나 가져올 수 있습니다. 예를 들어 다음과 같이 속성을 설정하고 가져올 수 있습니다.

objectPtr->property = value;        // set property value  
variable = objectPtr->property;     // get property value  

다음을 코딩할 필요가 없습니다.

objectPtr->PutProperty(value);      // set property value  
variable = objectPtr->GetProperty;  // get property value  

컴파일러는 선언된 대체 구문 및 속성을 읽거나 쓰는지 여부에 따라 적절한 Get-, Put- 또는 PutRefProperty 호출을 생성합니다.

__declspec(property...) 컴파일러 지시문은 get, put 또는 getput 대체 구문만 선언할 수 있습니다. 읽기 전용 작업에는 get 선언만 있습니다. 쓰기 전용 작업에는 put 선언만 있습니다. 읽기 및 쓰기가 모두 있는 작업에는 getput 선언이 모두 있습니다.

이 지시문에서는 두 개의 선언만 사용할 수 있습니다. 그러나 각 속성에는 GetProperty, PutProperty, PutRefProperty의 세 가지 속성 함수가 포함될 수 있습니다. 이 경우 두 가지 형식의 속성에만 대체 구문이 있습니다.

예를 들어 Command 개체 ActiveConnection 속성은 GetActiveConnectionPutRefActiveConnection에 대한 대체 구문을 사용하여 선언됩니다. 실제로는 일반적으로 열려 있는 Connection 개체(Connection 개체 포인터)를 이 속성에 배치하려고 하기 때문에 PutRef- 구문은 좋은 선택입니다. 반면에 Recordset 개체에는 Get-, Put- 및 PutRefActiveConnection 작업이 있지만 대체 구문은 없습니다.

컬렉션, GetItem 메서드, Item 속성

ADO는 Fields, Parameters, Properties, Errors를 비롯한 여러 컬렉션을 정의합니다. Visual C++에서 GetItem(index) 메서드는 컬렉션의 멤버를 반환합니다. Index는 컬렉션에 있는 멤버의 숫자 인덱스 또는 멤버 이름을 포함하는 문자열인 Variant 값입니다.

__declspec(property...) 컴파일러 지시문은 Item 속성을 각 컬렉션의 기본 GetItem() 메서드에 대한 대체 구문으로 선언합니다. 대체 구문은 대괄호를 사용하며 배열 참조와 비슷하게 표시됩니다. 일반적으로 두 형식은 다음과 같이 표시됩니다.

  
      collectionPtr->GetItem(index);  
collectionPtr->Item[index];  

예를 들어 pubs 데이터베이스의 authos 테이블에서 파생된 rs라는 Recordset 개체의 필드에 값을 할당합니다. Item() 속성을 사용하여 Recordset 개체 Fields 컬렉션의 세 번째 Field에 액세스합니다(컬렉션은 0부터 인덱싱됨, 세 번째 필드의 이름은 au_fname으로 가정함). 그런 다음, Field 개체에서 Value() 메서드를 호출하여 문자열 값을 할당합니다.

Visual Basic에서 다음 네 가지 방법으로 표현할 수 있습니다(마지막 두 형식은 Visual Basic에 고유하고 다른 언어에는 해당 항목이 없음).

rs.Fields.Item(2).Value = "value"  
rs.Fields.Item("au_fname").Value = "value"  
rs(2) = "value"  
rs!au_fname = "value"  

위의 처음 두 형식에 대한 Visual C++의 해당 항목은 다음과 같습니다.

rs->Fields->GetItem(long(2))->PutValue("value");   
rs->Fields->GetItem("au_fname")->PutValue("value");  

-or-(Value 속성에 대한 대체 구문도 표시됨)

rs->Fields->Item[long(2)]->Value = "value";  
rs->Fields->Item["au_fname"]->Value = "value";  

컬렉션을 반복하는 예제는 “ADO 참조”의 “ADO 컬렉션” 섹션을 참조하세요.

COM 관련 데이터 형식

일반적으로 ADO API 참조에서 찾는 Visual Basic 데이터 형식은 Visual C++에 해당 항목이 있습니다. 여기에는 Visual Basic Byte의 경우 부호 없는 문자, Integer의 경우 short, Long의 경우 long과 같은 표준 데이터 형식이 포함됩니다. 구문 Indexesto에서 지정된 메서드 또는 속성의 피연산자에서 필요한 항목을 정확히 확인합니다.

이 규칙의 예외는 COM 관련 데이터 형식인 Variant, BSTR, SafeArray입니다.

변형

Variant는 값 멤버와 데이터 형식 멤버를 포함하는 구조적 데이터 형식입니다. Variant에는 다른 Variant, BSTR, Boolean, IDispatch 또는 IUnknown 포인터, 통화, 날짜 등을 비롯한 다양한 다른 데이터 형식이 포함될 수 있습니다. COM은 한 데이터 형식을 다른 데이터 형식으로 쉽게 변환할 수 있는 메서드도 제공합니다.

_variant_t 클래스는 Variant 데이터 형식을 캡슐화하고 관리합니다.

ADO API 참조에서 메서드 또는 속성 피연산자가 값을 사용한다고 표시되면 일반적으로 값이 _variant_t로 전달됨을 의미합니다.

ADO API 참조 항목의 매개 변수 섹션에서 피연산자가 Variant라고 표시되면 이 규칙이 명시적으로 적용됩니다. 한 가지 예외는 설명서에서 피연산자가 표준 데이터 형식(예: Long 또는 Byte) 또는 열거형을 사용한다고 표시되는 경우입니다. 또 다른 예외는 피연산자가 String을 사용하는 경우입니다.

BSTR

BSTR(Basic STRing)은 문자열과 문자열 길이를 포함하는 구조적 데이터 형식입니다. COM은 BSTR을 할당, 조작, 해제하는 메서드를 제공합니다.

_bstr_t 클래스는 BSTR 데이터 형식을 캡슐화하고 관리합니다.

ADO API 참조에서 메서드 또는 속성이 String 값을 사용한다고 표시되면 값이 _bstr_t 형식임을 의미합니다.

_variant_t 및 _bstr_t 클래스 캐스팅

인수에서 _variant_t 또는 _bstr_t를 작업에 명시적으로 코딩할 필요가 없는 경우가 많습니다. _variant_t 또는 _bstr_t 클래스에 인수의 데이터 형식과 일치하는 생성자가 있는 경우 컴파일러는 적절한 _variant_t 또는 _bstr_t를 생성합니다.

그러나 인수가 모호한 경우, 즉 인수의 데이터 형식이 둘 이상의 생성자와 일치하는 경우에는 적절한 데이터 형식으로 인수를 캐스팅하여 올바른 생성자를 호출해야 합니다.

예를 들어 Recordset::Open 메서드에 대한 선언은 다음과 같습니다.

    HRESULT Open (  
        const _variant_t & Source,  
        const _variant_t & ActiveConnection,  
        enum CursorTypeEnum CursorType,  
        enum LockTypeEnum LockType,  
        long Options );  

ActiveConnection 인수는 연결 문자열로 코딩하거나 열린 Connection 개체에 대한 포인터로 코딩할 수 있는 _variant_t에 대한 참조를 사용합니다.

DSN=pubs;uid=MyUserName;pwd=MyPassword;”와 같은 문자열 또는 “(IDispatch *) pConn”과 같은 포인터를 전달하는 경우 올바른 _variant_t가 암시적으로 생성됩니다.

참고 항목

Windows 인증을 지원하는 데이터 원본 공급자에 연결하는 경우 연결 문자열의 사용자 ID 및 암호 정보 대신 Trusted_Connection=yes 또는 Integrated Security=SSPI를 지정해야 합니다.

또는 “_variant_t((IDispatch *) pConn, true)”와 같은 포인터가 포함된 _variant_t를 명시적으로 코딩할 수 있습니다. 캐스트 (IDispatch *)는 IUnknown 인터페이스에 대한 포인터를 사용하는 다른 생성자를 사용하여 모호성을 해결합니다.

ADO가 IDispatch 인터페이스라는 사실은 거의 언급하지 않았지만 매우 중요합니다. ADO 개체에 대한 포인터를 Variant로 전달해야 할 때마다 해당 포인터는 IDispatch 인터페이스에 대한 포인터로 캐스팅되어야 합니다.

마지막 사례는 선택적 기본값 true를 사용하여 생성자의 두 번째 부울 인수를 명시적으로 코딩합니다. 이 인수를 사용하면 Variant 생성자가 해당 AddRef() 메서드를 호출합니다. 이 메서드는 ADO 메서드 또는 속성 호출이 완료될 때 _variant_t::Release() 메서드를 자동으로 호출하여 ADO를 보정합니다.

SafeArray

SafeArray는 다른 데이터 형식의 배열을 포함하는 구조적 데이터 형식입니다. SafeArray는 각 배열 차원의 경계에 대한 정보를 포함하고 해당 범위 내 배열 요소에 대한 액세스를 제한하기 때문에 안전이라고 합니다.

ADO API 참조에서 메서드 또는 속성이 배열을 사용하거나 반환한다고 표시되면 메서드 또는 속성은 네이티브 C/C++ 배열이 아닌 SafeArray를 사용하거나 반환함을 의미합니다.

예를 들어 Connection 개체 OpenSchema 메서드의 두 번째 매개 변수에는 Variant 값 배열이 필요합니다. 해당 Variant 값은 SafeArray의 요소로 전달되어야 하며 SafeArray는 다른 Variant의 값으로 설정되어야 합니다. OpenSchema의 두 번째 인수로 전달되는 다른 Variant입니다.

또한 Find 메서드의 첫 번째 인수는 값이 1차원 SafeArrayVariant입니다. AddNew의 선택적 첫 번째 및 두 번째 인수 각각은 1차원 SafeArray입니다. GetRows 메서드의 반환 값은 값이 2차원 SafeArrayVariant입니다.

누락 및 기본 매개 변수

Visual Basic에서는 메서드에서 누락 매개 변수를 허용합니다. 예를 들어 Recordset 개체 Open 메서드에는 5개 매개 변수가 있지만 중간 매개 변수를 건너뛰고 후행 매개 변수를 제외할 수 있습니다. 기본 BSTR 또는 Variant는 누락 피연산자의 데이터 형식에 따라 대체됩니다.

C/C++에서는 모든 피연산자를 지정해야 합니다. 데이터 형식이 문자열인 누락 매개 변수를 지정하려면 null 문자열이 포함된 _bstr_t를 지정합니다. 데이터 형식이 Variant인 누락 매개 변수를 지정하려면 DISP_E_PARAMNOTFOUND 값과 VT_ERROR 형식의 _variant_t를 지정합니다. 또는 #import 지시문에서 제공하는 해당 항목 _variant_t 상수 vtMissing을 지정합니다.

일반적인 vtMissing 사용에 대한 예외로 세 가지 메서드가 있습니다. 해당 메서드는 ConnectionCommand 개체의 Execute 메서드와 Recordset 개체의 NextRecordset 메서드입니다. 서명은 다음과 같습니다.

_RecordsetPtr <A HREF="mdmthcnnexecute.htm">Execute</A>( _bstr_t CommandText, VARIANT * RecordsAffected,   
        long Options );  // Connection  
_RecordsetPtr <A HREF="mdmthcmdexecute.htm">Execute</A>( VARIANT * RecordsAffected, VARIANT * Parameters,   
        long Options );  // Command  
_RecordsetPtr <A HREF="mdmthnextrec.htm">NextRecordset</A>( VARIANT * RecordsAffected );  // Recordset  

RecordsAffectedParameters 매개 변수는 Variant에 대한 포인터입니다. Parameters는 실행 중인 명령을 수정하는 단일 매개 변수 또는 매개 변수 배열을 포함하는 Variant의 주소를 지정하는 입력 매개 변수입니다. RecordsAffected는 메서드의 영향을 받는 행 수가 반환되는 Variant의 주소를 지정하는 출력 매개 변수입니다.

Command 개체 Execute 메서드에서 Parameters&vtMissing(권장됨) 또는 null 포인터(NULL 또는 0)로 설정하여 매개 변수를 지정하지 않음을 나타냅니다. Parameters가 null 포인터로 설정된 경우 메서드는 내부적으로 vtMissing의 해당 항목을 대체한 다음, 작업을 완료합니다.

모든 메서드에서 RecordsAffected를 null 포인터로 설정하여 영향을 받는 레코드 수를 반환해서는 안 됨을 나타냅니다. 이 경우 null 포인터는 누락 매개 변수가 아니라 메서드가 영향을 받는 레코드 수를 삭제해야 함을 나타냅니다.

따라서 이 세 가지 메서드의 경우 다음과 같은 항목을 코딩하는 것이 좋습니다.

pConnection->Execute("commandText", NULL, adCmdText);   
pCommand->Execute(NULL, NULL, adCmdText);  
pRecordset->NextRecordset(NULL);  

오류 처리

COM에서 대부분의 작업은 함수가 성공적으로 완료되었는지 여부를 나타내는 HRESULT 반환 코드를 반환합니다. #import 지시문은 각 “원시” 메서드 또는 속성 주위에 래퍼 코드를 생성하고 반환된 HRESULT를 확인합니다. HRESULT가 실패를 나타내는 경우 래퍼 코드는 HRESULT 반환 코드를 인수로 사용하여 _com_issue_errorex()를 호출함으로써 COM 오류를 throw합니다. COM 오류 개체는 try-catch 블록에서 catch할 수 있습니다. (효율성을 위해 _com_error 개체에 대한 참조를 catch합니다.)

이는 ADO 오류이며 ADO 작업 실패로 인해 발생합니다. 기본 공급자가 반환한 오류는 Connection 개체 Errors 컬렉션에 Error 개체로 표시됩니다.

#import 지시문은 ADO .dll에서 선언된 메서드 및 속성에 대한 오류 처리 루틴만 만듭니다. 그러나 고유한 오류 검사 매크로 또는 인라인 함수를 작성하여 이와 동일한 오류 처리 메커니즘을 활용할 수 있습니다. 예제는 Visual C++ 확장 항목 또는 다음 섹션의 코드를 참조하세요.

Visual Basic 규칙의 Visual C++ 해당 항목

다음은 Visual Basic으로 코딩된 ADO 설명서의 여러 규칙과 Visual C++의 해당 항목에 대한 요약입니다.

ADO 개체 선언

Visual Basic에서 ADO 개체 변수(이 경우 Recordset 개체에 해당)는 다음과 같이 선언됩니다.

Dim rst As ADODB.Recordset  

ADODB.Recordset” 절은 레지스트리에 정의된 Recordset 개체의 ProgID입니다. Record 개체의 새 인스턴스는 다음과 같이 선언됩니다.

Dim rst As New ADODB.Recordset  

또는

Dim rst As ADODB.Recordset  
Set rst = New ADODB.Recordset  

Visual C++에서 #import 지시문은 모든 ADO 개체에 대한 스마트 포인터 형식 선언을 생성합니다. 예를 들어 _Recordset 개체를 가리키는 변수는 _RecordsetPtr 형식이며 다음과 같이 선언됩니다.

_RecordsetPtr  rs;  

_Recordset 개체의 새 인스턴스를 가리키는 변수는 다음과 같이 선언됩니다.

_RecordsetPtr  rs("ADODB.Recordset");  

또는

_RecordsetPtr  rs;  
rs.CreateInstance("ADODB.Recordset");  

또는

_RecordsetPtr  rs;  
rs.CreateInstance(__uuidof(_Recordset));  

CreateInstance 메서드를 호출한 후 다음과 같이 변수를 사용할 수 있습니다.

rs->Open(...);  

한 경우에 “.” 연산자는 변수가 클래스 인스턴스(rs.CreateInstance)였던 것처럼 사용되고, 또 다른 경우에 “->” 연산자는 변수가 인터페이스에 대한 포인터(rs->Open)였던 것처럼 사용됩니다.

클래스 인스턴스가 인터페이스에 대한 포인터처럼 동작할 수 있도록 “->” 연산자가 오버로드되기 때문에 한 변수를 두 가지 방법으로 사용할 수 있습니다. 인스턴스 변수의 프라이빗 클래스 멤버는 _Recordset 인터페이스에 대한 포인터를 포함합니다. “->” 연산자는 해당 포인터를 반환합니다. 반환된 포인터는 _Recordset 개체의 멤버에 액세스합니다.

누락 매개 변수 코딩 - String

Visual Basic에서 누락된 String 피연산자를 코딩해야 하는 경우에는 피연산자를 생략하면 됩니다. Visual C++에서는 피연산자를 지정해야 합니다. 값으로 빈 문자열이 있는 _bstr_t를 코딩합니다.

_bstr_t strMissing(L"");  

누락 매개 변수 코딩 - Variant

Visual Basic에서 누락된 Variant 피연산자를 코딩해야 하는 경우에는 피연산자를 생략하면 됩니다. Visual C++에서는 모든 피연산자를 지정해야 합니다. _variant_t를 특수 값 DISP_E_PARAMNOTFOUND 및 형식 VT_ERROR로 설정하여 누락된 Variant 매개 변수를 코딩합니다. 또는 #import 지시문에서 제공하는 해당 항목인 미리 정의된 상수 vtMissing을 지정합니다.

_variant_t  vtMissingYours(DISP_E_PARAMNOTFOUND, VT_ERROR);   

- 또는 다음 사용 -

...vtMissing...;  

Variant 선언

Visual Basic에서 Variant는 다음과 같이 Dim 문으로 선언됩니다.

Dim VariableName As Variant  

Visual C++에서는 변수를 _variant_t 형식으로 선언합니다. 몇몇 도식 표현 _variant_t 선언은 다음과 같습니다.

참고 항목

이 선언은 단지 자체 프로그램에서 코딩할 내용에 대한 대략적인 아이디어를 제공합니다. 자세한 내용은 아래 예제 및 Visual C++ 설명서를 참조하세요.

_variant_t  VariableName(value);  
_variant_t  VariableName((data type cast) value);  
_variant_t  VariableName(value, VT_DATATYPE);  
_variant_t  VariableName(interface * value, bool fAddRef = true);  

Variants 배열 사용

Visual Basic에서 Variants 배열은 Dim 문으로 코딩하거나 다음 예제 코드에 표시된 대로 Array 함수를 사용할 수 있습니다.

Public Sub ArrayOfVariants  
Dim cn As ADODB.Connection  
Dim rs As ADODB.Recordset  
Dim fld As ADODB.Field  
  
    cn.Open "DSN=pubs"  
    rs = cn.OpenSchema(adSchemaColumns, _  
        Array(Empty, Empty, "authors", Empty))  
    For Each fld in rs.Fields  
        Debug.Print "Name = "; fld.Name  
    Next fld  
    rs.Close  
    cn.Close  
End Sub  

다음 Visual C++ 예제에서는 _variant_t와 함께 사용되는 SafeArray를 사용하는 방법을 보여 줍니다.

주의

다음 메모는 코드 예제의 주석으로 처리된 섹션에 해당합니다.

  1. 다시 한 번 말하지만, TESTHR() 인라인 함수는 기존 오류 처리 메커니즘을 활용하기 위해 정의됩니다.

  2. 1차원 배열만 필요하므로 범용 SAFEARRAYBOUND 선언 및 SafeArrayCreate 함수 대신 SafeArrayCreateVector를 사용할 수 있습니다. 다음은 SafeArrayCreate를 사용하는 코드의 모양입니다.

       SAFEARRAYBOUND   sabound[1];  
       sabound[0].lLbound = 0;  
       sabound[0].cElements = 4;  
       pSa = SafeArrayCreate(VT_VARIANT, 1, sabound);  
    
  3. 열거형 상수 adSchemaColumns를 통해 식별되는 스키마는 TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME이라는 네 개 제약 조건 열과 연결됩니다. 따라서 네 개 요소가 있는 Variant 값 배열이 만들어집니다. 그런 다음, 세 번째 열 TABLE_NAME에 해당하는 제약 조건 값이 지정됩니다.

    반환되는 Recordset는 제약 조건 열의 하위 집합인 여러 열로 구성됩니다. 반환된 각 행에 대한 제약 조건 열의 값은 해당 제약 조건 값과 동일해야 합니다.

  4. SafeArrays에 익숙한 사람들은 SafeArrayDestroy()가 종료 전에 호출되지 않는다는 사실에 놀랄 수 있습니다. 실제로 이 경우 SafeArrayDestroy()를 호출하면 런타임 예외가 발생합니다. 그 이유는 vtCriteria에 대한 소멸자는 _variant_t가 범위를 벗어날 때 VariantClear()를 호출하여 SafeArray를 해제하기 때문입니다. _variant_t를 수동으로 지우지 않고 SafeArrayDestroy를 호출하면 소멸자가 잘못된 SafeArray 포인터를 지우려고 합니다.

    SafeArrayDestroy가 호출된 경우 코드는 다음과 같습니다.

          TESTHR(SafeArrayDestroy(pSa));  
       vtCriteria.vt = VT_EMPTY;  
          vtCriteria.parray = NULL;  
    

    그러나 _variant_tSafeArray를 관리하도록 하는 것이 훨씬 더 간단합니다.

// Visual_CPP_ADO_Prog_1.cpp  
// compile with: /EHsc  
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")  
  
// Note 1  
inline void TESTHR( HRESULT _hr ) {   
   if FAILED(_hr)   
      _com_issue_error(_hr);   
}  
  
int main() {  
   CoInitialize(NULL);  
   try {  
      _RecordsetPtr pRs("ADODB.Recordset");  
      _ConnectionPtr pCn("ADODB.Connection");  
      _variant_t vtTableName("authors"), vtCriteria;  
      long ix[1];  
      SAFEARRAY *pSa = NULL;  
  
      pCn->Provider = "sqloledb";  
      pCn->Open("Data Source='(local)';Initial Catalog='pubs';Integrated Security=SSPI", "", "", adConnectUnspecified);  
      // Note 2, Note 3  
      pSa = SafeArrayCreateVector(VT_VARIANT, 1, 4);  
      if (!pSa)   
         _com_issue_error(E_OUTOFMEMORY);  
  
      // Specify TABLE_NAME in the third array element (index of 2).   
      ix[0] = 2;        
      TESTHR(SafeArrayPutElement(pSa, ix, &vtTableName));  
  
      // There is no Variant constructor for a SafeArray, so manually set the   
      // type (SafeArray of Variant) and value (pointer to a SafeArray).  
  
      vtCriteria.vt = VT_ARRAY | VT_VARIANT;  
      vtCriteria.parray = pSa;  
  
      pRs = pCn->OpenSchema(adSchemaColumns, vtCriteria, vtMissing);  
  
      long limit = pRs->GetFields()->Count;  
      for ( long x = 0 ; x < limit ; x++ )  
         printf( "%d: %s\n", x + 1, ((char*) pRs->GetFields()->Item[x]->Name) );  
      // Note 4  
      pRs->Close();  
      pCn->Close();  
   }  
   catch (_com_error &e) {  
      printf("Error:\n");  
      printf("Code = %08lx\n", e.Error());  
      printf("Code meaning = %s\n", (char*) e.ErrorMessage());  
      printf("Source = %s\n", (char*) e.Source());  
      printf("Description = %s\n", (char*) e.Description());  
   }  
   CoUninitialize();  
}  

속성 Get/Put/PutRef 사용

Visual Basic에서 속성 이름은 속성이 검색, 할당 또는 참조 할당되었는지 여부에 따라 정규화되지 않습니다.

Public Sub GetPutPutRef  
Dim rs As New ADODB.Recordset  
Dim cn As New ADODB.Connection  
Dim sz as Integer  
cn.Open "Provider=sqloledb;Data Source=yourserver;" & _  
         "Initial Catalog=pubs;Integrated Security=SSPI;"  
rs.PageSize = 10  
sz = rs.PageSize  
rs.ActiveConnection = cn  
rs.Open "authors",,adOpenStatic  
' ...  
rs.Close  
cn.Close  
End Sub  

이 Visual C++ 예제에서는 Get/Put/PutRefProperty를 보여 줍니다.

주의

다음 메모는 코드 예제의 주석으로 처리된 섹션에 해당합니다.

  1. 이 예제에서는 두 가지 형식의 누락 문자열 인수인 명시적 상수 strMissing과 컴파일러가 Open 메서드의 범위에 대해 존재하는 임시 _bstr_t를 만드는 데 사용할 문자열을 사용합니다.

  2. 피연산자의 형식이 이미 (IDispatch *)이므로 rs->PutRefActiveConnection(cn)의 피연산자를 (IDispatch *)로 캐스팅할 필요가 없습니다.

// Visual_CPP_ado_prog_2.cpp  
// compile with: /EHsc  
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")  
  
int main() {  
   CoInitialize(NULL);  
   try {  
      _ConnectionPtr cn("ADODB.Connection");  
      _RecordsetPtr rs("ADODB.Recordset");  
      _bstr_t strMissing(L"");  
      long oldPgSz = 0, newPgSz = 5;  
  
      // Note 1  
      cn->Provider = "sqloledb";  
      cn->Open("Data Source='(local)';Initial Catalog=pubs;Integrated Security=SSPI;", strMissing, "", adConnectUnspecified);  
  
      oldPgSz = rs->GetPageSize();  
      // -or-  
      // oldPgSz = rs->PageSize;  
  
      rs->PutPageSize(newPgSz);  
      // -or-  
      // rs->PageSize = newPgSz;  
  
      // Note 2  
      rs->PutRefActiveConnection( cn );  
      rs->Open("authors", vtMissing, adOpenStatic, adLockReadOnly, adCmdTable);  
      printf("Original pagesize = %d, new pagesize = %d\n", oldPgSz, rs->GetPageSize());  
      rs->Close();  
      cn->Close();  
  
   }  
   catch (_com_error &e) {  
      printf("Description = %s\n", (char*) e.Description());  
   }  
   ::CoUninitialize();  
}  

GetItem(x) 및 Item[x] 사용

이 Visual Basic 예제에서는 Item()에 대한 표준 및 대체 구문을 보여 줍니다.

Public Sub GetItemItem  
Dim rs As New ADODB.Recordset  
Dim name as String  
rs = rs.Open "authors", "DSN=pubs;", adOpenDynamic, _  
         adLockBatchOptimistic, adTable  
name = rs(0)  
' -or-  
name = rs.Fields.Item(0)  
rs(0) = "Test"  
rs.UpdateBatch  
' Restore name  
rs(0) = name  
rs.UpdateBatch  
rs.Close  
End Sub  

이 Visual C++ 예제에서는 Item을 보여 줍니다.

참고 항목

다음 참고는 코드 예제의 주석으로 처리된 섹션에 해당합니다. 컬렉션에 Item을 사용하여 액세스하는 경우 적절한 생성자가 호출되도록 인덱스 2long으로 캐스팅해야 합니다.

// Visual_CPP_ado_prog_3.cpp  
// compile with: /EHsc  
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")  
  
void main() {  
   CoInitialize(NULL);  
   try {  
      _ConnectionPtr cn("ADODB.Connection");  
      _RecordsetPtr rs("ADODB.Recordset");  
      _variant_t vtFirstName;  
  
      cn->Provider = "sqloledb";  
      cn->Open("Data Source='(local)';Initial Catalog=pubs;Integrated Security=SSPI;", "", "", adConnectUnspecified);  
  
      rs->PutRefActiveConnection( cn );  
      rs->Open("authors", vtMissing, adOpenStatic, adLockOptimistic, adCmdTable);  
      rs->MoveFirst();  
  
      // Note 1. Get a field.  
      vtFirstName = rs->Fields->GetItem((long)2)->GetValue();  
      // -or-  
      vtFirstName = rs->Fields->Item[(long)2]->Value;  
  
      printf( "First name = '%s'\n", (char*)( (_bstr_t)vtFirstName) );  
  
      rs->Fields->GetItem((long)2)->Value = L"TEST";  
      rs->Update(vtMissing, vtMissing);  
  
      // Restore name  
      rs->Fields->GetItem((long)2)->PutValue(vtFirstName);  
      // -or-  
      rs->Fields->GetItem((long)2)->Value = vtFirstName;  
      rs->Update(vtMissing, vtMissing);  
      rs->Close();  
   }  
   catch (_com_error &e) {  
      printf("Description = '%s'\n", (char*) e.Description());  
   }  
   ::CoUninitialize();  
}  

(IDispatch *)를 사용하여 ADO 개체 포인터 캐스팅

다음 Visual C++ 예제에서는 (IDispatch *)를 사용하여 ADO 개체 포인터를 캐스팅하는 방법을 보여 줍니다.

주의

다음 메모는 코드 예제의 주석으로 처리된 섹션에 해당합니다.

  1. 명시적으로 코딩된 Variant에서 열린 Connection 개체를 지정합니다. 올바른 생성자가 호출되도록 (IDispatch *)를 사용하여 캐스팅합니다. 또한 두 번째 _variant_t 매개 변수를 기본값 true로 명시적으로 설정하므로 Recordset::Open 작업이 종료되면 개체 참조 수가 올바릅니다.

  2. (_bstr_t)는 캐스트가 아니라 Value에 의해 반환된 Variant에서 _bstr_t 문자열을 추출하는 _variant_t 연산자입니다.

(char*)는 캐스트가 아니라 _bstr_t 개체의 캡슐화된 문자열에 대한 포인터를 추출하는 _bstr_t 연산자입니다.

이 코드 섹션에서는 _variant_t_bstr_t 연산자의 몇 가지 유용한 동작을 보여 줍니다.

// Visual_CPP_ado_prog_4.cpp  
// compile with: /EHsc  
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile")  
  
int main() {  
   CoInitialize(NULL);  
   try {  
      _ConnectionPtr pConn("ADODB.Connection");  
      _RecordsetPtr pRst("ADODB.Recordset");  
  
      pConn->Provider = "sqloledb";  
      pConn->Open("Data Source='(local)';Initial Catalog='pubs';Integrated Security=SSPI", "", "", adConnectUnspecified);  
  
      // Note 1.  
      pRst->Open("authors", _variant_t((IDispatch *) pConn, true), adOpenStatic, adLockReadOnly, adCmdTable);  
      pRst->MoveLast();  
  
      // Note 2.  
      printf("Last name is '%s %s'\n",   
         (char*) ((_bstr_t) pRst->GetFields()->GetItem("au_fname")->GetValue()),  
         (char*) ((_bstr_t) pRst->Fields->Item["au_lname"]->Value));  
  
      pRst->Close();  
      pConn->Close();  
   }  
   catch (_com_error &e) {  
      printf("Description = '%s'\n", (char*) e.Description());  
   }     
   ::CoUninitialize();  
}