Microsoft KB Archive/231351

= DOC: ADO VC Tutorial in MSDN Has Compile/Run-Time Errors =

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:


 * 1) Start MSDN, click the Contents tab.
 * 2) Navigate as follows: Platform SDK, Data Access Service, Microsoft Data Access 2.1 SDK, Microsoft ActiveX Data Objects (ADO), Microsoft ADO Programmer's Reference.
 * 3) 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:

Error Code = 800a0bb9 Code meaning = Unknown error 0x800A0BB9 Source = ADODB.Recordset Description = The application is using arguments that are of the wrong type, are out of acceptable range, or are in conflict with one another.

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:

Error Code = 800a0cc1 Code meaning = Unknown error 0x800A0CC1 Source = ADODB.Properties Description = ADO could not find the object in the collection corresponding to the name or ordinal reference requested by the application.

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
 * 1) define INITGUID
 * 2) import "c:\Program Files\Common Files\System\ADO\msado15.dll"   no_namespace rename("EOF", "EndOfFile")
 * 3) include 
 * 4) include 

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.

