本教程以新版 Microsoft Visual C++ Extensions 为特征。VC++ Extensions 删除了对繁琐的 VARIANT 数据类型的使用。
本教程还使用了 #import 伪指令,它将 ADO Typelib 转换到头文件中,这个头文件使一些 ADO 的功能在使用和外观上类似 Microsoft Visual Basic 中相应的用法。
注意 在该范例中发布和使用的绑定宏已经过更改,不再与原始文档相同。有关当前宏定义的详细信息,请参阅头文件 icrsint.h。
#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_ENTRY2(1, adVarChar, m_szau_lname, sizeof(m_szau_lname), lau_lnameStatus, false) ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_szau_fname, sizeof(m_szau_fname), lau_fnameStatus, false) ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, 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;// 步骤 1 — 打开连接 pConn->Open("dsn=pubs;", "sa", "", adConnectUnspecified);// 步骤 2 — 创建命令 // 步骤 3 — 执行命令 pRs->Open("select * from authors", _variant_t(pConn), adOpenDynamic, adLockOptimistic, adCmdText); if (FAILED(hr = pRs->QueryInterface(__uuidof(IADORecordBinding), (LPVOID*)&picRs))) _com_issue_error(hr); if (FAILED(hr = picRs->BindToRecordset(&rs))) _com_issue_error(hr);// 步骤 4 — 操作数据 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("\a\tName: %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); 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 = (long) adFilterNone;// 步骤 5 — 更新数据 pConn->BeginTrans(); try { pRs->UpdateBatch(adAffectAll); // 步骤 6-A — 结束更新 pConn->CommitTrans(); } catch (_com_error) { // 步骤 6-B — 结束更新 pRs->Filter = (long) adFilterConflictingRecords; pRs->MoveFirst(); while (VARIANT_FALSE == pRs->EndOfFile) { printf("\a\tConflict: 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(); } } catch (_com_error &e) { dump_com_error(e); } CoUninitialize(); }
VC++ 教程到此结束。