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:
- 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:
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 :