Article ID: 231351
Article Last Modified on 10/17/2003
APPLIES TO
- Microsoft Data Access Components Software Development Kit 2.0
- Microsoft Data Access Components Software Development Kit 2.1
- Microsoft ActiveX Data Objects 2.0
- Microsoft ActiveX Data Objects 2.1
This article was previously published under Q231351
SUMMARY
The ADO Visual C++ Tutorial in MSDN has problems in the code that can cause one or more compilation or run-time errors.
To get to this tutorial, do the following:
- Start MSDN, click the Contents tab.
- Navigate as follows: Platform SDK, Data Access Service, Microsoft Data Access 2.1 SDK, Microsoft ActiveX Data Objects (ADO), Microsoft ADO Programmer's Reference.
- From the Microsoft ADO Programmer's Reference, navigate as follows: Learning ADO, ADO and RDS Tutorials, ADO Tutorial, ADO Tutorial (VC++).
One error that the user may get at run time is the following:
The above error is caused by the wrong syntax in the Open method on the recordset in following line:
pRs->Open("select * from authors", _variant_t (pConn), adOpenDynamic, adLockOptimistic, adCmdText);
Another error that the user may get at run time is the following:
The above error was caused by not using client-side cursors for an "Optimize" property in the following line of code:
pRs->Fields->GetItem("au_lname")->Properties->GetItem("Optimize")->Value = true;
MORE INFORMATION
Following is the code that corrects the above mentioned errors. Just replace the code from the sample with the following code:
// START ADO VC++ TUTORIAL #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(__uuidof(Connection)); // FIX #1: DON'T USE PROGID! _RecordsetPtr pRs(__uuidof(Recordset)); // FIX #2: DON'T USE PROGID! CCustomRs rs; // Step 1: Open a connection pConn->Open("dsn=pubs;", "sa", "", adConnectUnspecified); // Step 2: Create a command // Step 3: Execute the command pRs->CursorLocation = adUseClient; // FIX #3: NEED CLIENT CURSOR FOR BATCH UPDATES! pRs->Open("select * from authors", _variant_t((IDispatch*)pConn), // FIX #4: MUST CAST SMART POINTER TO LPDISPATCH! adOpenDynamic, adLockBatchOptimistic, // FIX #5: MUST USE adLockBatchOptimistic adCmdText); 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->Item["au_lname"]->Properties->Item["Optimize"]->Value = true; // FIX #6: USE PROPER SMART POINTER SYNTAX. //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; // Step 5: Update the data pConn->BeginTrans(); try { pRs->UpdateBatch(adAffectAll); // Step 6, part A: Conclude the update pConn->CommitTrans(); } catch (_com_error) { // Step 6, part B: Conclude the update 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(); } // END ADO VC++ TUTORIAL
Microsoft has confirmed that this is a bug in ADO VC Tutorial in MSDN version April 99 for Winodws 95/98/NT4.0.
REFERENCES
For additional information about using ADO in Visual C++, please see the following articles in the Microsoft Knowledge Base:
220152 Sample: ADOVC1 Simple ADO/VC++ Application
185033 FILE: Adoacc.exe Demonstrates Using ADO with Access 97
Additional query words: problem problematic MDAC
Keywords: kbdatabase kbdocfix kbdocerr KB231351