How To Invoke OLE DB Service Component Within an OLE DB Application (253803)
The information in this article applies to:
- Microsoft OLE DB 2.0
- Microsoft OLE DB 2.1
- Microsoft OLE DB 2.5
- Microsoft OLE DB 2.6
This article was previously published under Q253803 SUMMARY
In Microsoft OLE DB 1.x, consumers generally connect to a provider through the root enumerator, or they pass the provider's CLSID to CoCreateInstance, as in this example:
//Create an instance of CLSID_MSDASQL
CoCreateInstance(CLSID_MSDASQL, NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,(void**)pIDBInitialize);
To take advantage of the common services that are provided as part of OLE DB version 2.0 or OLE DB version 2.5 or 2.6, OLE DB consumers need to create provider instances by calling methods in either the IDataInitialize or the IDBPromptInitialize interfaces. The DataInitialize interface is supported through the Service Component Manager, which can be instantiated with CLSID_MSDAINITIALIZE. The IDBPromptInitialize interface is supported by the Data Links component, which can be instantiated with CLSID_ DataLinks.
For example, to create an instance of a provider that can take advantage of OLE DB 2.0 services, based on the provider's CLSID, the code would look like this:
//Create an instance of the OLE DB Initialization Component
CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER,
IID_IDataInitialize,(void**)&pIDataInitialize);
//Create an instance of CLSID_MSDASQL with supported Services
pIDataInitialize->CreateDBInstance(CLSID_MSDASQL, NULL,
CLSCTX_INPROC_SERVER,NULL, IID_IDBInitialize,(IUnknown**)&pIDBInitialize);
OLE DB services are automatically invoked any time the consumer creates an OLE DB data source object through IDataInitialize or IDBPromptInitialize. NOTE: OLE DB Services are automatically invoked by default when you use Microsoft ActiveX Data Objects (ADO).
MORE INFORMATIONHow To Enable or Disable Services for a Provider
You can enable or disable individual OLE DB services, by default, for all
applications that access a single provider. To do this, add an
OLEDB_SERVICES registry entry under the provider's CLSID, with a DWORD value that specifies the services to enable or disable as follows: |
All services (the default) | 0xffffffff | All except Pooling and AutoEnlistment | 0xfffffffe | All except Client Cursor | 0xfffffffb | All except Pooling, Enlistment, and Cursor | 0xfffffff0 | No services | 0x00000000 | No aggregation, all services disabled | <missing key> |
How to Override Provider Service Defaults
The provider's registry value for OLEDB_ SERVICES is returned as the default value for the DBPROP_ INIT_ OLEDBSERVICES initialization property on the data source object.
As long as the registry entry exists, the provider's objects are aggregated and the user can override the provider's default setting for enabled services by setting the DBPROP_ INIT_ OLEDBSERVICES property prior to initialization. To enable or disable a particular service, the user gets the current value of the DBPROP_ INIT_ OLEDBSERVICES property, sets or clears the bit for the particular property to be enabled or disabled, and then resets the property.
You can set DBPROP_ INIT_ OLEDBSERVICES directly in OLE DB, or in the connection string passed to ADO or IDataInitialize:: GetDatasource. The values that correspond to enable or disable individual services are in the list that follows: DBPROP_INIT_OLEDBSERVICES |
All services | DBPROPVAL_OS_ENABLEALL | All except Pooling and AutoEnlistment | (DBPROPVAL_OS_ENABLEALL&~DBPROPVAL_OS_RESOURCEPOOLING) | All except Client Cursor | (DBPROPVAL_OS_ENABLEALL&~DBPROPVAL_OS_CLIENTCURSOR) | All except pooling, enlistment, and cursor | (DBPROPVAL_OS_ENABLEALL&~DBPROPVAL_OS_RESOURCEPOOLING | No services | ~DBPROPVAL_OS_ENABLEALL |
|
All services (the default) | "OLE DB Services = -1;" | All except Pooling and AutoEnlistment | "OLE DB Services = -2;" | All except Client Cursor | "OLE DB Services = -5;" | All except pooling, enlistment, and cursor | "OLE DB Services = -7;" | No services | "OLE DB Services = 0;" |
If the registry entry does not exist for the provider, the Component Managers does not aggregate the provider's objects, and no services are
invoked, even if explicitly requested by the user.
Here is a code example that illustrates how to invoke the service component from an OLE DB application. This example creates a CLSID_ MSDAINITIALIZE provider and implements session pooling,
which is one of the service components that OLE DB provides. NOTE: - This program assumes you use a single processor computer.
- You must have OLEDB_SERVICES set to 0xffffffff or 0xfffffffb under
the SQLOLEDB for session pooling to work.
- If you set DBPROP_INIT_PROMPT to DBPROMPT_PROMPT, you will not get session pooling. This is because the provider by default assumes a different connection when you are opening an INIT PROMPT dialog box
#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <oledb.h>
#include <oledberr.h>
#include <msdaguid.h>
#include <oleauto.h>
#include <msdasc.h>
void main(int argc, char* argv[])
{
IUnknown * pIUnknown = NULL;
BOOL * pbValue = FALSE;
CLSID clsid;
HRESULT hr;
IDataInitialize* pIDataInitialize = NULL;
IDBInitialize * pIDBInitialize = NULL;
IDBProperties* pIDBProperties = NULL;
hr = CoInitialize(NULL);
//Invoke the OLE DB Service Components with the MSDAINITIALIZE
//provider. Session pooling is enabled while the
//IDataInitialize interface pointer is held.
hr = CoCreateInstance(CLSID_MSDAINITIALIZE, NULL, CLSCTX_INPROC_SERVER, IID_IDataInitialize, (void**)&pIDataInitialize);
if( FAILED(hr = CLSIDFromProgID(L"SQLOLEDB", &clsid) ) )
return;
const ULONG nProps = 5;
DBPROP InitProperties[nProps];
DBPROPSET rgInitPropSet;
for (ULONG i = 0; i < nProps; i++)
{
VariantInit(&InitProperties[i].vValue);
InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[i].colid = DB_NULLID;
}
//Level of prompting performed to complete the connection process.
InitProperties[0].dwPropertyID = DBPROP_INIT_PROMPT;
InitProperties[0].vValue.vt = VT_I2;
InitProperties[0].vValue.iVal = DBPROMPT_NOPROMPT;
//Datasource name.
InitProperties[1].dwPropertyID = DBPROP_INIT_DATASOURCE;
InitProperties[1].vValue.vt = VT_BSTR;
InitProperties[1].vValue.bstrVal = SysAllocString(OLESTR("YourServerName"));
//Userid.
InitProperties[2].dwPropertyID = DBPROP_AUTH_USERID;
InitProperties[2].vValue.vt = VT_BSTR;
InitProperties[2].vValue.bstrVal = SysAllocString(OLESTR("YouUserId"));
//Password.
InitProperties[3].dwPropertyID = DBPROP_AUTH_PASSWORD;
InitProperties[3].vValue.vt = VT_BSTR;
InitProperties[3].vValue.bstrVal = SysAllocString(OLESTR("YourPassword"));
//Catalog : Your database name.
InitProperties[4].dwPropertyID = DBPROP_INIT_CATALOG;
InitProperties[4].vValue.vt = VT_BSTR;
InitProperties[4].vValue.bstrVal = SysAllocString(OLESTR("YourDatabaseName"));
//Assign the property structures to the property set.
rgInitPropSet.guidPropertySet = DBPROPSET_DBINIT;
rgInitPropSet.cProperties = nProps;
rgInitPropSet.rgProperties = InitProperties;
//Here in a loop you connect to the database 10 times and
//each time you release the connection at the end. Note, you //only see one connection in the server for these 10
//connections.
for (int j = 0; j < 10; j++)
{
//Use the IDataInitialize interface to load the SQLOLEDB provider and create an IDBInitialize interface.
hr = pIDataInitialize->CreateDBInstance(clsid, NULL, CLSCTX_INPROC_SERVER, NULL, IID_IDBInitialize, (IUnknown**)&pIDBInitialize);
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
hr = pIDBProperties->SetProperties(1, &rgInitPropSet);
pIDBProperties->Release();
hr = pIDBInitialize->Initialize();
if (FAILED(hr))
return;
//These variables are for Command creation.
IDBCreateSession* pIDBCreateSession;
IDBCreateCommand* pIDBCreateCommand;
IRowset* pIRowset;
ICommandText* pICommandText;
//Here is a sample Select statement. Change it as //neccessary:
LPCTSTR wSQLString = OLESTR("Select au_lname, au_fname from authors");
LONG cRowsAffected;
//Get the DB Session object.
hr = pIDBInitialize->QueryInterface(IID_IDBCreateSession,(void**)&pIDBCreateSession);
if (FAILED(hr))
return;
//Create the session, and get an interface for command creation.
hr = pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand,(IUnknown**)&pIDBCreateCommand);
pIDBCreateSession->Release();
if (FAILED(hr))
return;
//Create the command object.
hr = pIDBCreateCommand->CreateCommand(NULL, IID_ICommandText,(IUnknown**)&pICommandText);
pIDBCreateCommand->Release();
if (FAILED(hr))
return;
hr = pICommandText->SetCommandText(DBGUID_DBSQL, wSQLString);
//Execute the command.
hr = pICommandText->Execute(NULL,IID_IRowset,NULL,&cRowsAffected,(IUnknown**)&pIRowset);
pICommandText->Release();
if (FAILED(hr))
return;
pIRowset->Release();
//NOTE: Uncommenting the next line disables session pooling, and prevents the sessions
//from being pooled. Per the MSDASDK Help file:
//"Initialization information is changed by calling IDBInitialize::Uninitialize."
//pIDBInitialize->Uninitialize();
// Simply Release() the sessions and they return to the pool.
// If pooling works properly, the connections to the server are
// still alive after the IDBInitialize interface is released.
pIDBInitialize->Release();
}
// The connections should be closed after the IDataInitialize interface is released.
pIDataInitialize->Release();
CoUninitialize();
}
Modification Type: | Minor | Last Reviewed: | 7/1/2004 |
---|
Keywords: | kbhowto KB253803 |
---|
|