Visual C++ での ADO プログラミング
ADO API リファレンスでは、Microsoft Visual Basic に似た構文を使って、ADO アプリケーション プログラミング インターフェイス (API) の機能を説明しています。 対象ユーザーはすべてのユーザーですが、ADO プログラマは多様な言語を使います。たとえば、Visual Basic、Visual C++ (#import ディレクティブを使う場合と使わない場合)、Visual J++ (ADO/WFC クラス パッケージを使用) などです。
注意
Microsoft では、2004 年に Visual J++ のサポートを終了しました。
この多様性に対応するため、Visual C++ 構文用 ADO のインデックスでは、Visual C++ 言語固有の構文と、API リファレンスの機能、パラメーター、例外的な動作などに関する一般的な説明へのリンクが提供されます。
ADO は、COM (コンポーネント オブジェクト モデル) インターフェイスを使用して実装されています。 ただし、プログラマにとっては、特定のプログラミング言語の方が他の言語よりも COM の操作が簡単になります。 たとえば、Visual Basic プログラマにとっては COM の使用に関するほぼすべての詳細が暗黙的に処理されますが、Visual C++ プログラマはそれらの詳細に自分で対処する必要があります。
以下のセクションは、ADO と #import ディレクティブを使う C および C++ プログラマ向けに詳細情報をまとめたものです。 COM に固有のデータ型 (Variant、BSTR、SafeArray) と、エラー処理 (_com_error) に焦点を当てています。
#import コンパイラ ディレクティブの使用
#import Visual C++ コンパイラ ディレクティブを使うと、ADO のメソッドとプロパティの操作を簡素化できます。 このディレクティブは、ADO .dll (Msado15.dll) などのタイプ ライブラリを含むファイルの名前を受け取り、typedef 宣言、インターフェイスのスマート ポインター、列挙定数を含むヘッダー ファイルを生成します。 各インターフェイスは、クラスにカプセル化 (またはラップ) されています。
クラス内の操作 (つまり、メソッドまたはプロパティの呼び出し) ごとに、操作を直接呼び出す宣言 (つまり、操作の "生" の形式) と、生の操作を呼び出して、操作が正常に実行されなかった場合に COM エラーをスローする宣言があります。 操作がプロパティである場合は、通常、Visual Basic のような構文を持つ操作の代替構文を作成するコンパイラ ディレクティブがあります。
プロパティの値を取得する操作には、Get<プロパティ> という形式の名前が付けられています。 プロパティの値を設定する操作には、Put<プロパティ> という形式の名前が付けられています。 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 の代替構文のみです。 読み取り専用の操作は get 宣言のみを持ちます。書き込み専用の操作は put 宣言のみを持ちます。読み取りと書き込みの両方を行う操作は、get と put 両方の宣言を持ちます。
このディレクティブでは、2 つの宣言のみが可能です。ただし、それぞれのプロパティは、Get<プロパティ>、Put<プロパティ>、PutRef<プロパティ> という 3 つのプロパティ関数を持つことができます。 その場合、プロパティの 2 つの形式のみが代替構文を持ちます。
たとえば、Command オブジェクトの ActiveConnection プロパティは、GetActiveConnection と PutRefActiveConnection の代替構文で宣言されています。 PutRef- 構文は適切な選択肢になります。なぜなら実際は、通常、開いている Connection オブジェクト (つまり、Connection オブジェクト ポインター) をこのプロパティに格納する必要があるためです。 一方、Recordset オブジェクトには Get-、Put-、PutRefActiveConnection の操作がありますが、代替構文はありません。
コレクション、GetItem メソッド、Item プロパティ
ADO では、Fields、Parameters、Properties、Errors などのいくつかのコレクションが定義されています。 Visual C++ では、GetItem(index) メソッドがコレクションのメンバーを返します。 Index は Variant であり、その値はコレクション内のメンバーの数値インデックスか、メンバーの名前を含む文字列です。
__declspec(property...) コンパイラ ディレクティブは、各コレクションの基本的な GetItem() メソッドの代替構文として Item プロパティを宣言します。 代替構文では角かっこが使われ、配列の参照に似ています。 一般に、2 つの形式は次のようになります。
collectionPtr->GetItem(index);
collectionPtr->Item[index];
たとえば、pubs データベースの authors テーブルから派生した、rs という名前の Recordset オブジェクトのフィールドに値を代入します。 Item() プロパティを使って、Recordset オブジェクトの Fields コレクションの 3 番目の Field にアクセスします (コレクションのインデックスは 0 から始まります。3 番目のフィールドの名前は au_fname であると仮定します)。 次に、Field オブジェクトの Value() メソッドを呼び出して、文字列値を代入します。
これは、Visual Basic では次の 4 つの方法で表すことができます (最後の 2 つの形式は Visual Basic に固有のものであり、他の言語に同等の形式はありません)。
rs.Fields.Item(2).Value = "value"
rs.Fields.Item("au_fname").Value = "value"
rs(2) = "value"
rs!au_fname = "value"
Visual C++ で上の最初の 2 つの形式に相当するものは、次のようになります。
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 固有のデータ型
一般に、ADO API リファレンスに記載されているすべての Visual Basic データ型は、Visual C++ にも相当するものがあります。 これには標準データ型も含まれます。たとえば、Visual Basic の Byte に相当する unsigned char、Integer に相当する short、Long に相当する long などです。 構文インデックスを参照して、指定されたメソッドやプロパティのオペランドには何が必要かを確認してください。
この規則の例外は、COM に固有のデータ型: Variant、BSTR、SafeArray です。
Variant
Variant は、値メンバーとデータ型メンバーを含む構造化データ型です。 Variant には、別の Variant や、BSTR、Boolean、IDispatch または IUnknown ポインター、通貨、日付など、その他のさまざまなデータ型を含めることができます。 COM には、あるデータ型を別のデータ型に簡単に変換できるようにするメソッドも用意されています。
_variant_t クラスは、Variant データ型をカプセル化して管理します。
ADO API リファレンスでメソッドやプロパティのオペランドが値を受け取ると記載されている場合、通常、その値は _variant_t で渡されることを意味します。
この規則は、ADO API リファレンスのトピックの「パラメーター」セクションに、オペランドが Variant であると記載されている場合、特に当てはまります。 1 つの例外は、オペランドが標準データ型 (Long や Byte、列挙型など) を受け取ることがドキュメントで明示的に示されている場合です。 もう 1 つの例外は、オペランドが 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
引数は _variant_t への参照を受け取ります。これは、接続文字列または開いている Connection オブジェクトへのポインターとしてコーディングできます。
"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 インターフェイスへのポインターとしてキャストする必要があります。
最後のケースでは、コンストラクターの 2 番目のブール値引数を、その省略可能な既定値 true
で明示的にコーディングしています。 この引数により、Variant コンストラクターでその AddRef() メソッドが呼び出されます。これにより、ADO のメソッドまたはプロパティの呼び出しが完了したときに _variant_t::Release() メソッドを自動的に呼び出す ADO が補正されます。
SafeArray
SafeArray は、他のデータ型の配列を含む構造化データ型です。 SafeArray が safe (安全) と呼ばれる理由は、配列の各次元の境界に関する情報が含まれていて、それらの境界内の配列要素へのアクセスが制限されるためです。
ADO API リファレンスで、メソッドやプロパティが配列を受け取ったり返したりすると記載されている場合、そのメソッドまたはプロパティは、ネイティブの C/C++ 配列ではなく SafeArray を受け取ったり返したりすることを意味します。
たとえば、Connection オブジェクトの OpenSchema メソッドの 2 番目のパラメーターには、Variant 値の配列が必要です。 これらの Variant 値は、SafeArray の要素として渡す必要があり、その SafeArray は別の Variant の値として設定する必要があります。 OpenSchema の 2 番目の引数として渡されるのは、その別の Variant です。
その他の例としては次のようなものがあります。Find メソッドの最初の引数は、値が 1 次元の SafeArray である Variant です。AddNew の省略可能な 1 番目と 2 番目の引数は、それぞれ 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 を指定します。 または、同等の _variant_t 定数である vtMissing を指定します。これは、#import ディレクティブによって指定されます。
vtMissing の一般的な使用に対する例外として、3 つのメソッドがあります。 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 と Parameters の各パラメーターは、Variant へのポインターです。 Parameters は、実行されているコマンドを変更する単一のパラメーター、またはパラメーターの配列が含まれている Variant のアドレスを指定する入力パラメーターです。 RecordsAffected は、Variant のアドレスを指定する出力パラメーターで、メソッドの影響を受ける行数が返されます。
Command オブジェクトの Execute メソッドで、Parameters を &vtMissing
(推奨) または Null ポインター (つまり、NULL またはゼロ (0) のいずれか) に設定することにより、パラメーターが指定されていないことを示します。
Parameters が Null ポインターに設定されている場合、メソッドでは内部的に vtMissing に相当するものが使用され、操作を完了します。
すべてのメソッドで、影響を受けるレコードの数を返す必要がないことを示すには、RecordsAffected を Null ポインターに設定します。 この場合、Null ポインターは省略したパラメーターというより、メソッドが影響を受けるレコードの数を破棄する必要があることを示すものです。
したがって、これら 3 つのメソッドでは、次のようなコードを記述することができます。
pConnection->Execute("commandText", NULL, adCmdText);
pCommand->Execute(NULL, NULL, adCmdText);
pRecordset->NextRecordset(NULL);
エラー処理
COM では、ほとんどの操作から、関数が正常に完了したかどうかを示す HRESULT リターン コードが返されます。 #import ディレクティブは、"生" の各メソッドまたはプロパティのラッパー コードを生成し、返された HRESULT をチェックします。 HRESULT が失敗を示している場合、ラッパー コードは、HRESULT リターン コードを引数として _com_issue_errorex() を呼び出すことによって、COM エラーをスローします。 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
) ことがわかります。
"->
" 演算子はオーバーロードされ、クラスのインスタンスがインターフェイスへのポインターのように動作できるようになるため、1 つの変数を 2 つの方法で使用できます。 インスタンス変数のプライベート クラス メンバーには、_Recordset インターフェイスへのポインターが含まれています。"->
" 演算子はそのポインターを返し、返されたポインターは _Recordset オブジェクトのメンバーにアクセスします。
省略したパラメーターのコーディング - String
Visual Basic で省略した String オペランドをコーディングする必要がある場合は、そのオペランドを省略するだけです。 Visual C++ では、そのオペランドを指定する必要があります。 値として空の文字列を持つ _bstr_t をコーディングします。
_bstr_t strMissing(L"");
省略したパラメーターのコーディング - Variant
Visual Basic で省略した Variant オペランドをコーディングする必要がある場合は、そのオペランドを省略するだけです。 Visual C++ では、すべてのオペランドを指定する必要があります。 型 VT_ERROR で特殊な値 DISP_E_PARAMNOTFOUND に設定された _variant_t を使って、省略した Variant パラメーターをコーディングします。 または、vtMissing を指定します。これは、#import ディレクティブによって提供される同等の定義済み定数です。
_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);
Variant の配列の使用
Visual Basic では、Dim ステートメントを使って Variant の配列をコーディングできます。または、次のコード例に示すように、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 を使う方法を示します。
メモ
以下のメモは、コード例のコメント付きセクションに対応しています。
繰り返しになりますが、TESTHR() インライン関数は既存のエラー処理メカニズムを利用するように定義されています。
必要なのは 1 次元配列だけなので、汎用の SAFEARRAYBOUND 宣言と SafeArrayCreate 関数の代わりに SafeArrayCreateVector を使用できます。 SafeArrayCreate を使用した場合のコードの外観を次に示します。
SAFEARRAYBOUND sabound[1]; sabound[0].lLbound = 0; sabound[0].cElements = 4; pSa = SafeArrayCreate(VT_VARIANT, 1, sabound);
列挙定数 adSchemaColumns によって識別されるスキーマは、4 つの制約列: TABLE_CATALOG、TABLE_SCHEMA、TABLE_NAME、CCOLUMN_NAME に関連付けられます。 したがって、4 つの要素を持つ Variant 値の配列が作成されます。 次に、3 番目の列 (TABLE_NAME) に対応する制約値を指定します。
返される Recordset は複数の列で構成され、そのサブセットは制約列です。 返される各行の制約列の値は、対応する制約値と同じである必要があります。
SafeArray に慣れているユーザーは、終了前に SafeArrayDestroy() が呼び出されていないことに驚くかもしれません。 実際、この場合に SafeArrayDestroy() を呼び出すと、実行時例外が発生します。 その理由は、_variant_t がスコープ外になると
vtCriteria
のデストラクターによって VariantClear() が呼び出され、SafeArray が開放されるためです。 _variant_t を手動でクリアすることなく SafeArrayDestroy を呼び出すと、デストラクターは無効な SafeArray ポインターをクリアしようとします。SafeArrayDestroy を呼び出す場合、コードは次のようになります。
TESTHR(SafeArrayDestroy(pSa)); vtCriteria.vt = VT_EMPTY; vtCriteria.parray = NULL;
ただし、_variant_t によって SafeArray が管理されるようにした方がはるかに簡単です。
// 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<プロパティ> を示しています。
メモ
以下のメモは、コード例のコメント付きセクションに対応しています。
この例では、2 つの形式の省略した文字列引数を使用します。つまり、明示的な定数 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 を示しています。
注意
以下のメモは、コード例のコメント付きセクションに対応しています。Item を使ってコレクションにアクセスする場合は、適切なコンストラクターが呼び出されるように、インデックス (2) を long にキャストする必要があります。
// 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 オブジェクト ポインターをキャストする方法を示しています。
メモ
以下のメモは、コード例のコメント付きセクションに対応しています。
明示的にコーディングされた Variant で、開いている Connection オブジェクトを指定します。 正しいコンストラクターが呼び出されるように、(IDispatch *) を使ってそれをキャストします。 また、2 番目の _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();
}