Microsoft KB Archive/174565

From BetaArchive Wiki

FILE: Adovc.exe Demonstrates How to Use ADO with Visual C++

ID: q174565



The information in this article applies to:

  • ActiveX Data Objects (ADO), version 1.0, included with:
    • Microsoft Visual C++, 32-bit Editions, version 5.0




SUMMARY

Adovc.exe is a sample that demonstrates using ActiveX Data Objects (ADO) within Visual C++ 5.0.


MORE INFORMATION

The following file is available for download from the Microsoft Software Library.

Note: After you click on the following link, please choose "Save this program to disk" from the File Download dialog box. Then, click Run on the Start menu and run the .exe file with the -d attribute, as in the following example:

C:\...\Adovc.exe -d


Adovc.exe

For more information about downloading files from the Microsoft Software Library, please see the following article in the Microsoft Knowledge Base:

Q119591 How to Obtain Microsoft Support Files from Online Services

What ADOVC Demonstrates

ADOVC is a sample that demonstrates using ActiveX Data Objects (ADO) within Visual C++ 5.0. Demonstration code for each of ADO's six classes is presented, with some additional code for handling more common issues such as output/return parameters and error/exception handling.

This sample actually has three separate projects, one for each of the three techniques that can be used with ADO inside Visual C++:

  • Via #import with Visual C++ 5.0
  • Via MFC OLE based classes for Visual C++ 5.0/4.2.
  • Via OLE SDK for Visual C++ 5.0/4.2

Three separate but nearly identical projects demonstrate each of these techniques. The projects were written so that WinDiff could be used on each directory. This helps identify the files that are different for each implementation, and then makes easy comparison to see what differences in the code each implementation imposes.

Three files in each sample contain all ADO specific code:

   Adoutils.h   - Contains the declaration of error/exception functions,
                  helper functions, and is where ADO declarations are
                  included in the project.
   Adoutils.cpp - Implementation of error/exception and helper functions.
   Adocore.cpp  - Actual ADO sample code, where ADO is demonstrated. 

Advantages of Using #import

  • #import offers very Visual Basic-like syntax for using ADO, easing much of the sting of "raw" COM. This can't be stressed enough, as it greatly simplifies referencing a specific item within a collection of a specific object. Consider the code fragment shown below and compare it to similar ADO coding techniques.
  • _bstr_t and _variant_t both make handling BSTR and VARIANT types relatively painless.
  • Failed HRESULT results in an exception being raised. _com_error automates the task of querying the IErrorInfo interface to acquire details of the error.
  • The gritty details of COM are hidden. That is with #import you should never have to AddRef, QueryInterface or Release.

Disadvantages of Using #import

  • Failed HRESULTS results in an exception being raised. You can alter this behavior as described in the following article in the Microsoft Knowledge Base:
  • Very few default arguments are provided. This is a noticeable difference between #import and Visual Basic (VB). With VB, optional arguments can be left off; however, with #import and ADO, very few defaults are actually picked up.
  • #import's exception handling mechanism has a bug wherein it does not correctly release the IErrorInfo interface when an error is raised through or by ADO. A three line fix, implemented in the ImportErrorEx() function is implemented, and the bug is described in detail in the following Visual C++ Knowledge Base article:

    Q173645 BUG: Access Violation in Msdaer.dll with _com_error Exceptions

Advantages of Using MFC-OLE

An advantage of using MFC-OLE is that it hides BSTR and VARIANTS from implementor, methods that return these types are modified so that the actual wrapper class returns a CString.

Disadvantages of Using MFC-OLE

Here are some disadvantages of using MFC-OLE:

  • HRESULTS are hidden and not returned by wrappers around methods.
  • Unlike #import and the headers provided for OLE-SDK, MFC-OLE does not read the typelib to provide values for the enumerated types defined there. This is best demonstrated in Adoutils.h, where three enums used by the helper functions are manually defined.
  • No ability to pass a license key [without overriding CreateDispatch()] for ADO 1.0 users. With ADO 1.5, MFC-OLE works just fine; however, with ADO 1.0, you must override two of the CreateDispatch() methods of the COleDispatchDriver class. This is demonstrated in the sample in the _Connection class.
  • Wrappers derived from COleDispatchDriver do not return HRESULTS. It is possible to receive failed HRESULTS bundled inside a ColeDispatchDriver exception, but there are scenarios where HRESULTS may not be received. It is also important that the exception handling, if it uses the Connection object's Errors collection, not process this collection unless you have a valid connection object. Otherwise it may be possible to generate exceptions within your exception handler.

Advantages of Using OLE-SDK

  • The bulk of the ADO samples that come with the OLE-DB SDK are written using raw OLE-SDK. The Adoid.h and Adoint.h files provide much of the kind of information #import generates off the typelib, only without the helpful wrapper classes or advanced bstr/variant handling, as well as automatically processing information from IErrorInfo.

Disadvantages of Using OLE-SDK

Here are some disadvantages of using OLE-SDK:

  • Requires more coding, especially managing BSTR and VARIANT types.
  • The actual sample code uses MFC classes, COleVarient and CString, to facilitate coding. A pure OLE-SDK application would not take advantage of the CString::AllocSysString() method. (However, if you don't want to use CString, this method's source is an excellent place to get a handy helper function to convert between char* and BSTR).

#import and the Advantage of "VB-Like Syntax"

Consider the following three code fragments to get the ActualSize property of a Field object, starting from the Recordset object:

    // #import
    CString    strTmp;

    strTmp.Format( "\t\t...Actual Size  = %ld",
                   Rs1->Fields->Item[_variant_t((long)0)]->ActualSize ); 

One line of code to go from Recordset to the ActualSize property. Now consider MFC-OLE:

   // MFC-OLE
   CString     strTmp;
   Fields      Flds1
   Field       Fld1;

   Flds1 = Rs1.GetFields();
   Fld1  = Flds1.GetItem( COleVariant( (long) 0 ) );
   strTmp.Format( "\t\t...Actual Size  = %ld", Fld1.GetActualSize ); 

Finally, consider the OLE-SDK equivalent code, which is nearly the same size as MFC-OLE, but gives more immediate error handling results than MFC- OLE is capable of.

   // OLE-SDK with ADOID.H and ADOINT.H
   CString     strTmp;
   ADOFields*  Flds1   = NULL;
   ADOField*   Fld1    = NULL;
   long        nTmp;


   if( SUCCEEDED ( hr ) ) hr = Rs1->get_Fields( & Flds1 );
   if( SUCCEEDED ( hr ) ) hr = Flds1->get_Item( COleVariant((long) 0 ),
                                                &Fld1 );
   if( SUCCEEDED ( hr ) ) hr = Fld1->get_ActualSize( &nTmp );
   if( SUCCEEDED ( hr ) ) strTmp.Format( "\t\t...Actual Size  = %ld",
                                         nTmp ); 

#import vs. COleDispatchDriver vs. OLE SDK

Based on the three projects in this sample, the recommended preference for using ADO in Visual C++ follows:

  1. #import because it dramatically simplifies using COM
  2. OLE SDK because you get back HRESULTS that are otherwise buried in MFC- OLE (when OLE SDK breaks, you know it)
  3. MFC-OLE, despite being an intermediate step towards #import, hides too much when it doesn't give you back a failed HRESULT

Other Tips for Using VC and ADO

  • When in doubt, use adCmdUnknown for options, especially for either Execute or Open methods. ADO will determine the correct option, whereas using adCmdText to open a stored procedure may cause problems (especially if trying to auto-fill the Parameters Collection).
  • Use vtEmpty and bstrEmpty for arguments that would otherwise be optional in Visual Basic.
  • Catch exceptions. In this case, modified versions of the helper routines provided from the ExceptEx sample were used to trap and log any exceptions raised by ADO or by the mechanisms used to manipulate ADO.

    For additional information, please see the following article in the Microsoft Knowledge Base:

    Q167802 SAMPLE: EXCEPTEX Traps MFC and Win32 Structured Exceptions

  • In this case, to manage a list box with a horizontal scroll bar, the CHorzListBox class was utilized as described in the following article in the Microsoft Knowledge Base:

    Q146437 SAMPLE: Horizontal Scrolling List Box in an MFC Class

  • Cracking Variants into something reasonable can be time-consuming. Embedded in multiple locations within MFC, and even various samples, is code to decipher a variant into a conventional type, such as CString. The definitive helper, though, ships with the DAOVIEW sample in Visual C++ 4.X/5.0 and its method: CCrack::strvariant. This method has been extracted from DAOVIEW and included with all three versions of the ADOVC projects as the function CrackStrVariant().

About the ADO* Series of Samples

This is one of several identical samples implemented using ADO within various products, as listed below. The advantage is that these articles have an identical interface/functionality, demonstrating both the similarities differences in using ADO with different languages and with different mechanisms within that language (where applicable).

QNumber                           Title 

Q172403 FILE: Adovb.exe Demonstrates How to Use ADO with Visual Basic
Q174565 FILE: Adovc.exe Demonstrates How to Use ADO with Visual C++
Q182782 FILE: Adovj.exe Demonstrates How to Use ADO with Visual J++
Q185033 FILE: Adoacc.exe Demonstrates Using ADO with Access 97

Other Knowledge Base Articles of Note

These articles provide detailed information not covered in this text about using ADO with various Visual C++ implementation mechanisms.

QNumber                           Title 

Q169496 INFO: Using ActiveX Data Objects (ADO) via #import in VC++
Q175993 INFO: Using ActiveX Data Objects (ADO) via MFC OLE in VC++
Q176342 INFO: Using ActiveX Data Objects (ADO) via OLE SDK in VC++

ADO Version 1.5

At the time of the writing of this sample, ADO 1.5 was not yet released, but was available publicly in beta. This sample has been written to work with either version, but there are some differences:

  • Most notably that version 1.5 requires an extra argument which must be - 1 for Open and Execute methods.
  • Code specific to 1.0 or 1.5 has a single line comment preceding it, as shown below:

            // ADO 1.0 Version
            Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty );
            // ADO 1.5 Version
            // Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 ); 
  • The MFCOLE sample requires you to remove Msado10.h and Msado15.cpp from the project, and add the already created Msado15.h and Msado15.cpp files.
  • The OLE-SDK sample will require you to have the OLE-DB 1.5 SDK, and more importantly the Adoid.h and Adoint.h files that will be included with that SDK. As of beta1 for that SDK, these files were not available, but they will be included with Beta2 as well as the final release of the OLE-DB SDK.

Additional query words:

Keywords          : kbsample kbADO kbVC 
Version           : WINDOWS:1.0
Platform          : WINDOWS 
Issue type        : 

Last Reviewed: October 6, 1999
© 1999 Microsoft Corporation. All rights reserved. Terms of Use.