This tutorial features the new Microsoft® Visual C++® Extensions. The VC++ Extensions eliminate the use of cumbersome VARIANT data types.
This tutorial also uses the #import directive, which converts the ADO typelib into a header file. That header file makes some ADO functionality similar in use and appearance to its equivalent in Microsoft® Visual Basic® .
#define INITGUID
#import "c:\Program Files\Common Files\System\ADO\msado15.dll"
no_namespace rename("EOF", "EndOfFile")
#include <stdio.h>
#include "icrsint.h"
void dump_com_error(_com_error &e)
{
printf("Error\n");
printf("\a\tCode = %08lx\n", e.Error());
printf("\a\tCode meaning = %s", e.ErrorMessage());
_bstr_t bstrSource(e.Source());
_bstr_t bstrDescription(e.Description());
printf("\a\tSource = %s\n", (LPCSTR) bstrSource);
printf("\a\tDescription = %s\n", (LPCSTR) bstrDescription);
}
class CCustomRs :
public CADORecordBinding
{
BEGIN_ADO_BINDING(CCustomRs)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(1, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, FALSE)
ADO_VARIABLE_LENGTH_BINDING_ENTRY(2, adVarChar, m_szau_fname,
sizeof(m_szau_fname), lau_fnameStatus, FALSE)
ADO_FIXED_LENGTH_BINDING_ENTRY(3, adChar, m_szphone,
sizeof(m_szphone), lphoneStatus, TRUE)
END_ADO_BINDING()
public:
CHAR m_szau_lname[41];
ULONG lau_lnameStatus;
CHAR m_szau_fname[41];
ULONG lau_fnameStatus;
CHAR m_szphone[12];
ULONG lphoneStatus;
};
VOID main()
{
HRESULT hr;
IADORecordBinding *picRs = NULL;
::CoInitialize(NULL);
try
{
_ConnectionPtr pConn("ADODB.Connection.1.5");
_RecordsetPtr pRs("ADODB.Recordset.1.5");
CCustomRs rs;
// Step 1—Open a connection
pConn->Open("dsn=pubs;uid=sa;pwd=;");
//Step 2—Create a command
// Step 3—Execute the command
pRs->Open("select * from authors", pConn,
adOpenDynamic, adLockOptimistic, adCmdUnknown);
if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs)))
_com_issue_error(hr);
if (FAILED(hr = picRs->BindToRecordset(&rs)))
_com_issue_error(hr);
// Step 4—Manipulate the data
pRs->Fields("au_lname").Optimize = TRUE;
pRs->Sort = "au_lname ASCENDING";
pRs->Filter = "phone LIKE '415 5*";
pRs->MoveFirst();
while (VARIANT_FALSE == pRs->EndOfFile)
{
printf("\a\tName: %s\t %s\tPhone: %s\n",
(lau_fnameStatus == adFldOK ? m_szau_fname : ""),
(lau_lnameStatus == adFldOK ? m_szau_lname): ""),
(lau_lphoneStatus == adFldOK ? m_szphone): ""));
if (lphoneStatus == adFldOK)
lmemcpy(m_szphone, "777", 3);
if (FAILED(hr = picRs->Update(&rs)))
_com_issue_error(hr);
// 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 = adFilterNone;
// Step 5—Update the data
pConn->BeginTrans();
pRs->UpdateBatch();
// Step 6, part A—Conclude the update
pConn->CommitTrans();
}
catch (_com_error &e)
{
dump_com_error(e);
}
catch (ADODB.Error &e)
{
pRS->Filter = adConflictingRecords;
pRs->MoveFirst();
while (VARIANT_FALSE == pRs->EndOfFile)
{
printf("\a\tConflict: Name = %s\t %s\n",
(lau_fnameStatus == adFldOK ? m_szau_fname : ""),
(lau_lnameStatus == adFldOK ? m_szau_lname): ""));
pRs->MoveNext();
}
// Step 6, part B—Conclude the update
pConn->Rollback();
}
if (picRs)
picRs->Release();
CoUninitialize();
}
This is the end of the VC++ tutorial.