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

ID: Q231351


The information in this article applies to:
  • Microsoft Data Access SDK, versions 2.0, 2.1
  • ActiveX Data Objects (ADO), versions 2.0, 2.1


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
#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 this to be 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:

Q220152 Sample: ADOVC1 Simple ADO/VC++ Application
Q185033 FILE: Adoacc.exe Demonstrates Using ADO with Access 97

Additional query words: problem problematic MDAC

Keywords : kbdocfix kbdocerr kbADO200 kbADO210 kbDatabase kbGrpVCDB kbGrpMDAC
Version : WINDOWS:2.0,2.1
Platform : WINDOWS
Issue type :


Last Reviewed: November 11, 1999
© 2000 Microsoft Corporation. All rights reserved. Terms of Use.