これは、#import ディレクティブを加えて Microsoft Visual C++ でコーディングされたADO チュートリアルです。このチュートリアルの目的については、「ADO チュートリアル」を参照してください。
#import ディレクティブは、ADO タイプ ライブラリから関数を生成してヘッダー ファイルに入れます。このヘッダー ファイルによって、ADO と Visual C++ が Microsoft Visual Basic のように使いやすくなります。
このチュートリアルでは、Visual C++ Extension for ADO も扱います。Visual C++ Extensions では自動的に変換が行われ、指定された Recordset のフィールドの値でローカル インスタンスの変数が設定されます。Visual C++ Extensions は、AddNew および Update メソッドもサポートします。
#import ディレクティブで、ADO の各プロパティとメソッドのためのエラー処理ルーチンが生成されます。このチュートリアルでは、非 ADO 関数のために同じエラー処理ルーチンを呼び出す便利な方法として、関数の TESTHR()
が提供されています。
#import "c:\Program Files\Common Files\System\ADO\msado15.dll" \
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include <icrsint.h> //Include support for VC++ Extensions
void dump_com_error(_com_error &e)
{
printf("Error:\n");
printf("Code = %08lx\n", e.Error());
printf("Code meaning = %s\n", e.ErrorMessage());
printf("Source = %s\n", (LPCSTR) e.Source());
printf("Description = %s\n", (LPCSTR) e.Description());
}
inline void TESTHR( HRESULT _hr )
{ if FAILED(_hr) _com_issue_error(_hr); }
class CCustomRs :
public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, m_szau_fname,
sizeof(m_szau_fname), lau_fnameStatus, false)
ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, false)
ADO_VARIABLE_LENGTH_ENTRY2(4, adVarChar, m_szphone,
sizeof(m_szphone), lphoneStatus, true)
END_ADO_BINDING()
public:
CHAR m_szau_fname[22];
ULONG lau_fnameStatus;
CHAR m_szau_lname[42];
ULONG lau_lnameStatus;
CHAR m_szphone[14];
ULONG lphoneStatus;
};
VOID main() // Tutorial in VC
{
IADORecordBinding *picRs = NULL;
::CoInitialize(NULL);
try
{
_ConnectionPtr pConn("ADODB.Connection");
_RecordsetPtr pRs("ADODB.Recordset");
_CommandPtr pCmd("ADODB.Command");
CCustomRs rs;
// Step 1: Open a connection
pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified);
// Step 2: Create a command
pCmd->CommandText = "select * from Authors";
pCmd->ActiveConnection = pConn;
// Step 3: Execute the command
pRs->CursorLocation = adUseClient;
pRs->Open((IDispatch *) pCmd, vtMissing,
adOpenStatic, adLockBatchOptimistic, adCmdUnspecified);
TESTHR(pRs->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs));
TESTHR(picRs->BindToRecordset(&rs));
// Step 4: Manipulate the data
pRs->Fields->GetItem("au_lname")->Properties->GetItem("Optimize")->Value = true;
pRs->Sort = "au_lname ASC";
pRs->Filter = "phone LIKE '415 5*'";
pRs->MoveFirst();
while (VARIANT_FALSE == pRs->EndOfFile)
{
printf("Name: %s\t %s\tPhone: %s\n",
(rs.lau_fnameStatus == adFldOK ? rs.m_szau_fname : ""),
(rs.lau_lnameStatus == adFldOK ? rs.m_szau_lname : ""),
(rs.lphoneStatus == adFldOK ? rs.m_szphone : ""));
if (rs.lphoneStatus == adFldOK)
memcpy(rs.m_szphone, "777", 3);
TESTHR(picRs->Update(&rs)); // Add change to the batch
// Change the current row of the Recordset.
// Recordset data for the new current row will automatically be
// extracted and placed in the CCustomRs C++ instance variables.
pRs->MoveNext();
}
pRs->Filter = (long) adFilterNone;
// Step 5: Update the data
pConn->BeginTrans();
try
{
pRs->UpdateBatch(adAffectAll);
// Step 6, part A: Conclude the update - Accept changes
pConn->CommitTrans();
}
// Step 6, part B: Conclude the update - Reject changes
catch (_com_error &e)
{
dump_com_error(e);
pRs->Filter = (long) adFilterConflictingRecords;
pRs->MoveFirst();
while (VARIANT_FALSE == pRs->EndOfFile)
{
printf("Conflict: Name = %s\t %s\n",
(rs.lau_fnameStatus == adFldOK ? rs.m_szau_fname : ""),
(rs.lau_lnameStatus == adFldOK ? rs.m_szau_lname : ""));
pRs->MoveNext();
}
pConn->RollbackTrans();
}
if (picRs) picRs->Release();
pRs->Close();
pConn->Close();
}
catch (_com_error &e)
{
dump_com_error(e);
}
CoUninitialize();
}
これで Visual C++ チュートリアルを終了します。