Using ADO in VC++
There are different ways to use ADO in VC++. See below article from MSDN. Using #import directive is easy and require less code to write.
MSDN Knowledge base Article ID: Q174565 says : There are three ways to use ADO in VC++
Via #import directive.
Via MFC OLE based classes.
Via OLE SDK
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.
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.
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.
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:
#import because it dramatically simplifies using COM
OLE SDK because you get back HRESULTS that are otherwise buried in MFC-
OLE (when OLE SDK breaks, you know it)
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.
Using ADO via the OLD DB SDK
Include ADO header files (adoid.h and adoint.h) in your source.
Add ADO import lib adoid.lib to linker input. These two options enables to create instances of ADO objects and access their member functions.
AdOConnection* pAdoConnection;
ADOCommand* pAdoCommand;
// Create instances of ADOConnection and ADCommand objects
CoCreateInstance(CLSID_CADOConnection, NULL, CLSCTX_INPROC_SERVER, IID_IADOConnection, (LPVOID*)&pAdoConnection );
CoCreateInstance(CLSID_CADOCommand, NULL, CLSCTX_INPROC_SERVER, IID_IADOCommand, (LPVOID*)&pAdoCommand );
// Call ADOConnection's Open method to connect to a database
pAdoConnection->Open(L"DSN name", L"usedid", L"password");
// pass ADOConnection to putref_ActiveConnection method of ADOCommand to connect ADOCommand object to ADOConnection.
pAdoCommand->putref_ActiveConnection(pAdoConnection);
'Now we can use Execute method of command to get recrodeset or pass a SQL qeury to database.
Using ADO via #import directive
Add the following statements to STDAFX.H file, right above the line //{{AFX_INSERT_LOCATION}}
#import "msado15.dll" rename("EOF", "ADOEOF")
using namespace ADODB;
These statements will create the COM compiler support wrapper classes for ADO in your project. If compiler doesn't file msado15.dll then you have to give full path of dll file. It should be in c:\program files\common files\system\ado.
Add these statements either in stdafx.h or cpp file in which you are using ADO.
#include "comdef.h"
#include "atlconv.h"
#include
using namespace std;
comdef.h defines the COM compiler support classes. atlconv.h defines macros for converting between ANSI, Unicode, and OLE strings. sstream is a c++ standard library that defines a standart string type.
Initialize COM library in your application's OnInitInstance function of your project's application class.
// Initialising COM
if ( FAILED (CoInitialize(NULL) ) )
{
AfxMessageBox("Unable to initialize COM");
return FALSE;
}
UnInitialize COM library on ExitInstance function of your project's application class.
CoUninitialize( );
After these four steps, now you can use ADO in your project. For example :-
_ConnectionPtr pAdoConnection;
_CommandPtr pAdoCommand;
// Create instances of ADOConnection and ADCommand objects
pAdoConnection.CreateInstance( __uuidof( Connection ) );
pAdoCommand.CreateInstance( __uuidof( Command ) );
// Call ADOConnection's Open method to connect to a database
pAdoConnection->Open(L"DSN name", L"usedid", L"password");
// pass ADOConnection to putref_ActiveConnection method of ADOCommand to connect ADOCommand object to ADOConnection.
pAdoCommand->ActiveConnection = pAdoConnection ;
Now we can use Execute method of command to get recrodeset or pass a SQL qeury to database. We will use #import method in all of our examples.