How Providers Work Effectively with Resource Pooling
To use OLE DB services, providers must support aggregation of all objects. This is a requirement of all OLE DB 1.5 and later providers. In addition, to work well with OLE DB resource pooling, providers must allow data source objects to be called on any thread, not just the one on which they were created. Specifically, providers must support the free thread model or, at minimum, the rental thread model. They must not be single or apartment threaded. The resource pool determines the thread model of the data source object by examining the value of the data source object's DBPROP_DSOTHREADMODEL property.
If the provider has a global connection state that might change while the data source object is in an initialized state, the provider should also support the DBPROP_RESETDATASOURCE property. This property is called before a connected data source object is reused, and gives the provider the opportunity to clean up the data source object's state. If the provider cannot clean up the data source object's state, it can return DBPROPSTATUS_NOTSETTABLE for the DBPROP_RESETDATASOURCE property and the data source object will not be reused.
Providers that connect to a remote database and can detect whether or not that connection may be lost should support the DBPROP_CONNECTIONSTATUS property. This property gives the OLE DB services the ability to detect dead connections and ensure that they are not returned to the pool.
Finally, automatic transaction enlistment must occur at the same level as resource pooling. Therefore, if a provider supports automatic transaction enlistment, it should support disabling it in favor of OLE DB automatic transaction enlistment, which occurs at the pooling level. To do this, the provider must support the DBPROP_INIT_OLEDBSERVICES property. OLE DB services will clear the DBPROPVAL_OS_TXNENLISTMENT flag when OLE DB automatic transaction enlistment is enabled. The provider should then disable its own support for automatic transaction enlistment.
When an OLE DB provider data source object is instantiated with the provider-implemented IClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject), the pUnkOuter pointer points to an object that will relay the accesses to the real controlling outer unknown object, which may change during the lifetime of the provider data source object. Providers should always call IUnknown methods on the pUnkOuter pointer when the provider wants to access the outer unknown object. Querying an IUnknown pointer on the data source object will get the controlling outer unknown object that is only guaranteed to be the real controlling outer unknown object at the time IUnknown::QueryInterface is called. Providers should not cache an IUnknown pointer queried from the data source object and then use the cached pointer later.