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과 같은 구문이 있는 작업에 대한 대체 구문을 만드는 컴파일러 지시문이 있습니다.
속성 값을 검색하는 작업은 형태가 속성의 이름을 가집니다. 속성의 값을 설정하는 작업의 이름은 PutProperty형태로 되어 있습니다. 속성 값을 ADO 개체에 대한 포인터로 설정하는 작업의 이름은 PutRef속성형식을 따릅니다.
다음 양식의 호출을 사용하여 속성을 얻거나 설정할 수 있습니다.
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-, 또는 PutRef속성 호출을 생성합니다.
__declspec(property...) 컴파일러 지시문은 가져오기, 저장하기, 또는 함수에 대한 가져오기 및 저장하기의 대체 구문을 선언할 수 있습니다. 읽기 전용 작업에는 get 선언이 있습니다. 쓰기 전용 작업에는 put 선언만 있습니다. 읽기 및 쓰기 작업에는 get 선언과 put 선언이 모두 있습니다.
이 지시문에서는 두 개의 선언만 가능합니다. 그러나 각 속성에는 GetProperty, PutProperty및 PutRef속성세 가지 속성 함수가 있을 수 있습니다. 이 경우 두 가지 형식의 속성에만 대체 구문이 있습니다.
예를 들어 Command 개체 ActiveConnection 속성은 GetActiveConnection 및 PutRefActiveConnection대한 대체 구문으로 선언됩니다. PutRef- 구문은 일반적으로 열려 있는 Connection 개체(즉, Connection 개체 포인터)를 이 속성에 배치하는 것이 좋습니다. 반면에 Recordset 개체에는 Get-, Put및 PutRefActiveConnection 작업이 있지만 대체 구문은 없습니다.
컬렉션, GetItem 메서드 및 Item 속성
ADO는 필드, 매개 변수, 속성및 오류포함한 여러 컬렉션을 정의합니다. Visual C++에서 GetItem(index) 메서드는 컬렉션의 멤버를 반환합니다. Index은 Variant의 값으로, 이는 컬렉션 내 멤버의 숫자 인덱스이거나 멤버 이름을 포함하는 문자열입니다.
__declspec(property...) 컴파일러 지시문은 각 컬렉션의 기본 GetItem() 메서드에 대한 대체 구문으로 Item 속성을 선언합니다. 대체 구문은 대괄호를 사용하며 배열 참조와 유사합니다. 일반적으로 두 양식은 다음과 같습니다.
collectionPtr->GetItem(index);
collectionPtr->Item[index];
예를 들어, pubs 데이터베이스의 authors 테이블에서 파생된 rsRecordset 개체의 필드에 값을 할당합니다. Item() 속성을 사용하여 fields 컬렉션에Recordset 개체의 세 번째 필드 액세스할 수 있습니다(컬렉션은 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");
-또는- (Value 속성에 대한 대체 구문도 표시됩니다.
rs->Fields->Item[long(2)]->Value = "value";
rs->Fields->Item["au_fname"]->Value = "value";
컬렉션을 반복하는 예제는 "ADO 참조"의 "ADO 컬렉션" 섹션을 참조하세요.
COM-Specific 데이터 형식
일반적으로 ADO API 참조에서 찾은 Visual Basic 데이터 형식에는 해당하는 Visual C++가 있습니다. 여기에는 Visual Basic Byte에 해당하는 부호 없는 문자, Integer에 해당하는 Short, Long에 해당하는 Long 같은 표준 데이터 형식이 포함됩니다. 구문 색인에서 지정된 메서드 또는 속성의 피연산자에 필요한 항목을 정확하게 확인하십시오.
이 규칙의 예외는 COM과 관련된 데이터 형식입니다. Variant, BSTR및 SafeArray.
변형
Variant 값 멤버와 데이터 형식 멤버를 포함하는 구조화된 데이터 형식입니다. 하나의 Variant은 다양한 범위의 데이터 형식을 포함할 수 있으며, 여기에는 또 다른 Variant, BSTR, Boolean, IDispatch 또는 IUnknown 포인터, 통화, 날짜 등이 포함될 수 있습니다. COM은 한 데이터 형식을 다른 데이터 형식으로 쉽게 변환할 수 있는 메서드도 제공합니다.
_variant_t 클래스는 Variant 데이터 형식을 캡슐화하고 관리합니다.
ADO API 참조에서 메서드나 속성의 피연산자가 값을 사용할 때, 이는 보통 값이 _variant_t에 전달된다는 것을 의미합니다.
이 규칙은 ADO API 참조의 주제에서 매개 변수 섹션이 피연산자를 Variant라고 명시할 때 명확히 참입니다. 한 가지 예외는 문서에서 피연산자가 Long 또는 바이트또는 열거형과 같은 표준 데이터 형식을 사용한다고 명시적으로 말하는 경우입니다. 또 다른 예외는 피연산자가 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=<password>;
"와 같은 문자열을 전달하거나 "(IDispatch *) pConn
"와 같은 포인터를 전달하면 올바른 _variant_t 암시적으로 생성됩니다.
메모
Windows 인증을 지원하는 데이터 원본 공급자에 연결하는 경우 연결 문자열의 사용자 ID 및 암호 정보 대신 Trusted_Connection=예 또는 통합 보안 = SSPI 지정해야 합니다.
또는 "_variant_t((IDispatch *) pConn, true)
"와 같은 포인터가 포함된 _variant_t 명시적으로 코딩할 수 있습니다. 캐스트 (IDispatch *)
은(는) IUnknown 인터페이스에 대한 포인터를 사용하는 또 다른 생성자와의 모호성을 해결합니다.
ADO가 IDispatch 인터페이스라는 사실은 거의 언급하지 않았지만 매우 중요합니다. ADO 개체에 대한 포인터를 Variant전달해야 할 때마다 해당 포인터는 IDispatch 인터페이스에 대한 포인터로 캐스팅되어야 합니다.
마지막 사례는 생성자의 두 번째 부울 인수를 선택적 기본값인 true
사용하여 명시적으로 코딩합니다. 이 인수를 사용하면 Variant 생성자가 해당 AddRef() 메서드를 호출하게 되며, ADO 메서드 또는 속성 호출이 완료되면 ADO가 _variant_t::Release() 메서드를 자동으로 호출하는 것을 보정합니다.
SafeArray
SafeArray 다른 데이터 형식의 배열을 포함하는 구조화된 데이터 형식입니다. ko-KR: SafeArray은 각 배열 차원의 경계에 대한 정보를 포함하고 해당 범위 내에서 배열 요소에 대한 접근을 제한하기 때문에 "안전한" 라고 불립니다.
ADO API 참조에서 메서드 또는 속성이 배열을 사용하거나 반환한다고 말하면 메서드 또는 속성이 네이티브 C/C++ 배열이 아닌 SafeArray사용하거나 반환한다는 의미입니다.
예를 들어, Connection 개체의 OpenSchema 메서드의 두 번째 매개 변수에는 Variant 값의 배열이 필요합니다. 이러한 Variant 값은 SafeArray요소로 전달되어야 하며, 그 SafeArray 는 후자의 Variant값으로 설정되어야 합니다. 다른 Variant가 OpenSchema의 두 번째 인수로 전달됩니다.
또한 Find 메서드의 첫 번째 인수는 값이 1차원 SafeArray인 Variant입니다. 각 선택적 첫 번째 및 두 번째 AddNew 인수는 1차원 SafeArray이며, 그리고 GetRows 메서드의 반환값은 값이 2차원 SafeArray인 Variant입니다.
누락된 매개 변수 및 기본 매개 변수
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일반적인 사용에 대한 예외입니다. 다음은 Connection 및 Command 개체의 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
매개 변수인 RecordsAffected 및 파라미터는 Variant에 대한 포인터입니다. 매개 변수 실행 중인 명령을 수정하는 단일 매개 변수 또는 매개 변수 배열을 포함하는 Variant 주소를 지정하는 입력 매개 변수입니다. RecordsAffected 은 메서드의 영향을 받는 행 수가 반환되는, Variant의 주소를 지정하는 출력 매개 변수입니다.
Command 개체의 Execute 메서드에서 매개 변수가 없음을 나타내려면, 매개 변수를 &vtMissing
(권장되는 방법) 또는 null 포인터(즉, NULL 또는 0)로 설정합니다.
매개 변수 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 블록으로 잡을 수 있습니다. (효율성을 위해 _com_error 개체에 대한 참조를 포획합니다.)
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 개체의 멤버에 액세스합니다.
누락된 매개 변수 코딩 - 문자열
Visual Basic에서 누락된 String 피연산자를 코딩해야 하는 경우 피연산자를 생략하기만 하면 됩니다. Visual C++에서 피연산자를 지정해야 합니다. 빈 문자열 값으로 _bstr_t를 작성합니다.
_bstr_t strMissing(L"");
누락된 매개 변수 코딩 - 변형
Visual Basic에서 누락된 Variant 피연산자를 코딩해야 하는 경우 피연산자를 생략하기만 하면 됩니다. Visual C++에서 모든 피연산자를 지정해야 합니다. 누락된 Variant 매개 변수를 특수 값 DISP_E_PARAMNOTFOUND 및 형식 VT_ERROR로 설정된 _variant_t를 사용하여 코딩합니다. 또는 vtMissing 를 지정합니다. 이것은 #import 지시문에서 제공하는 것과 동일한 미리 정의된 상수입니다.
_variant_t vtMissingYours(DISP_E_PARAMNOTFOUND, VT_ERROR);
-또는 사용 -
...vtMissing...;
Variant 선언
Visual Basic에서는 다음과 같이 Dim 문을 사용하여 Variant 선언됩니다.
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);
변형 배열 사용
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++ 예제는 SafeArray를 _variant_t와 함께 사용하는 방법을 보여줍니다.
노트
다음 메모는 코드 예제의 주석이 추가된 부분에 해당합니다.
다시 한번 TESTHR() 인라인 함수는 기존 오류 처리 메커니즘을 활용하도록 정의됩니다.
1차원 배열만 필요하므로 범용 SAFEARRAYBOUND 선언과 SafeArrayCreate 함수를 사용하는 대신, SafeArrayCreateVector함수를 사용하면 됩니다. 다음은 SafeArrayCreate를 사용한 코드의 모습입니다.
SAFEARRAYBOUND sabound[1]; sabound[0].lLbound = 0; sabound[0].cElements = 4; pSa = SafeArrayCreate(VT_VARIANT, 1, sabound);
adSchemaColumns 열거 상수로 식별되는 스키마는 TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME 및 COLUMN_NAME 네 개의 제약 조건 열과 연결됩니다. 따라서 4개의 요소가 있는 Variant 값의 배열이 만들어집니다. 그런 다음 세 번째 열인 TABLE_NAME 해당하는 제약 조건 값이 지정됩니다.
반환되는 Recordset 제약 조건 열의 하위 집합인 여러 열로 구성됩니다. 반환된 각 행에 대한 제약 조건 열의 값은 해당 제약 조건 값과 동일해야 합니다.
SafeArrays 익숙한 사람들은 SafeArrayDestroy()가 출구 전에 호출되지 않는다는 사실에 놀랄 수 있습니다. 실제로 이 경우 SafeArrayDestroy()를 호출하면 런타임 예외가 발생합니다. 그 이유는 _variant_t 범위를 벗어날 때
vtCriteria
소멸자가 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/PutRef속성을 설명합니다.
노트
다음 주석은 코드 예제의 주석이 달린 섹션에 대응합니다.
이 예제에서는 명시적 상수, strMissing및 컴파일러가 Open 메서드의 범위에 대해 존재하는 임시 _bstr_t 만드는 데 사용할 문자열이라는 두 가지 형식의 누락된 문자열 인수를 사용합니다.
피연산자의 유형이 이미
(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사용하여 컬렉션에 액세스하는 경우 2인덱스를 긴 캐스팅해야 적절한 생성자가 호출됩니다.
// 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();
}
ADO 개체 포인터를 (IDispatch *)로 캐스팅하기
다음 Visual C++ 예제에서는 (IDispatch *)를 사용하여 ADO 개체 포인터를 캐스팅하는 방법을 보여 줍니다.
노트
다음 참고는 코드 예제의 주석 처리된 섹션에 해당합니다.
명시적으로 코딩된 Variant내의 열린 Connection 개체를 지정합니다. 올바른 생성자가 호출되도록 (IDispatch *)를 사용하여 캐스팅합니다. 또한 두 번째 _variant_t 매개 변수를 true기본값으로 명시적으로 설정하므로 Recordset::Open 작업이 종료되면 개체 참조 수가 정확합니다.
(_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();
}