OLE DB defines a comprehensive set of interfaces for accessing a diverse range of data types, located in a variety of data stores. While the OLE DB Programmer's Reference can be intimidating in size, no one provider is expected to support all of the functionality defined in the reference. Providers only expose the interfaces that reflect the natural functionality of their data store. Providers all support a base level of functionality. Above that base level, common service components provide interoperability through generic implementations of extensions such as scrolling or notifications if the provider doesn't support them.
To meet its goal of providing data access to all types of data in a COM (Component Object Model) environment, OLE DB is designed as a component technology. In OLE DB, data sources expose the interfaces that reflect their functionality, and common components can be built on top of those interfaces to expose more robust data models. To define a component architecture, OLE DB identifies common characteristics between different data providers and services, and defines common interfaces to expose those characteristics. So, for example, while a rowset may be obtained through a number of very different mechanisms, the end result is still a rowset, with well-defined interfaces, methods and characteristics. With OLE DB, navigating the result of a complex multi-table join is no different than navigating the results of an opened text file containing tabular data. Defining common interfaces in this manner allows components to more efficiently augment the individual data provider's native functionality.
An OLE DB provider exposes OLE DB interfaces over some type of data. OLE DB providers include everything from a full SQL DBMS to a text file or data stream. Obviously these data providers have different functionality, and it's important not to limit that functionality. But at the same time it's not reasonable to expect all providers that expose simple tabular data to implement a full-blown query engine as well.
Once the base functionality is defined, the next step is to view the additional functionality as incremental additions to this base functionality. Thus, the more sophisticated providers can expose these advanced features in addition to the base level interfaces. Furthermore, individual service components can be built to implement these features on top of the simpler providers.
Developers writing OLE DB consumers can choose their level of interoperability with OLE DB providers. Consumers may be written to consume a specific provider, in which case they are designed to be aware of the functionality of the provider. Or they may be written to consume generic providers. In order to consume generic providers, the consumer may do one of the following:
The following table describes the minimum level of functionality that a consumer can expect to be supported when talking to any OLE DB provider. The table is broken into three columns:
Table 1 – Base Consumer Interfaces
Object | Base interfaces | Updatable |
DataSource | IConnectionPointContainer for: - IDBAsynchNotify |
|
IDatasource1 | ||
IDBAsynchStatus2 | ||
IDBCreateSession | ||
IDBInitialize | ||
IDBProperties | ||
IPersist | ||
ISupportErrorInfo | ||
DataSource Behavior | DBPROP_INIT_PROMPT3 | |
Session | IGetDataSource | |
IOpenRowset | ||
ISessionProperties | ||
ISupportErrorInfo | ||
Rowset | IAccessor | IRowsetChange |
IColumnsInfo | ||
IConnectionPointContainer for: - IDBAsynchNotify - IRowsetNotify |
||
IConvertType | ||
IDBAsynchStatus2 | ||
IRowset | ||
IRowsetFind | ||
IRowsetIdentity | ||
IRowsetInfo | ||
IRowsetLocate | ||
IRowPosition1 | ||
IRowsetScroll | ||
ISupportErrorInfo | ||
Rowset Behavior | DBPROP_ CANHOLDROWS | DBPROP_ REMOVEDELETED |
DBPROP_ CANFETCHBACKWARDS | DBPROP_ OWNUPDATEDELETE | |
DBPROP_ CANSCROLLBACKWARDS | DBPROP_ OWNINSERT |
1These interfaces are always supported by common components in the SDK. They are never implemented directly by providers.
2Support for IDBAsynchStatus does not require that the provider support any operations asynchronously. In the non-asynch case, the provider would simply block when creating or initializing the object, and return a completion status whenever GetStatus was called.
3DBPROP_INIT_PROMPT is required if any initialization properties are required in order to connect to the provider. If calling Initialize() succeeds on a freshly created Datasource, the provider does not need to support this property.
Providers support the native functionality of the data which they expose. However, in order to be consumed by generic consumers, providers must be able to support at least the minimum base consumer functionality defined in the previous table. You can develop a provider to support the minimum level of functionality in one of three ways:
In addition, providers may expose interfaces for the extended functionality described in the next section.
All providers must be either apartment or free threaded, and must support aggregation of the DataSource, Session, and Rowset. If applicable, providers must support the aggregation of the Command and View objects.
It's important for provider writers to implement the full set of interfaces that apply to their particular type of data. At a minimum, the provider must implement the interfaces and behavior listed in Table 2 to be considered a generic OLE DB provider. Providers implementing the minimum provider functionality can rely on common service components available in the SDK to implement the base consumer functionality, as shown in Figure 1.
Figure 1
Table 2 – Minimum Provider Interfaces
Object | Any base provider | Updatable providers |
DataSource | IDBCreateSession | |
IDBInitialize | ||
IDBProperties | ||
IPersist | ||
DataSource Behavior | DBPROP_INIT_PROMPT1 | |
Session | IGetDataSource | |
IOpenRowset | ||
ISessionProperties | ||
Rowset | IAccessor | IRowsetChange |
IConvertType | ||
IColumnsInfo | ||
IRowset | ||
IRowsetIdentity | ||
IRowsetInfo | ||
Rowset Behavior | DBPROP_CANHOLDROWS | DBPROP_ OWNUPDATEDELETE |
DBPROP_OWNINSERT | ||
DBPROP_ REMOVEDELETED |
1DBPROP_INIT_PROMPT is required if any initialization properties are required in order to connect to the provider. If calling Initialize() succeeds on a freshly created Datasource, the provider does not need to support this property.
Supporting an interface means supporting all methods within that interface. No methods return E_NOTIMPL.
Supporting a property means supporting the setting of and associated behavior of all possible values for a property.
Supporting the required rowset properties means that setting any combination of the required properties must yield a rowset that reflects at least those properties. It does not mean that those properties are always true for any rowset if the property has not been requested by the user.
Providers that implement the full set of base interfaces can be consumed by general consumers without the support of additional service components, as shown in Figure 2.
Figure 2
Providers implementing the following functionality in addition to the minimum provider functionality are consumed as base providers:
Table 3 – Full Interfaces for Base Providers
Object | Any base provider | Updatable providers |
DataSource | IConnectionPointContainer for: - IDBAsynchNotify |
|
IDBAsynchStatus | ||
ISupportErrorInfo | ||
Session | ISupportErrorInfo | |
Rowset | IDBAsynchStatus | |
IConnectionPointContainer for: - IRowsetNotify - IDBAsynchNotify |
||
IRowsetFind | ||
IRowsetLocate | ||
IRowsetScroll | ||
ISupportErrorInfo | ||
Rowset Behavior | DBPROP_ CANSCROLLBACKWARDS1 | |
DBPROP_ CANFETCHBACKWARDS1 |
1Providers that support the property DBPROP_CANSCROLLBACKWARDS must also support the property DBPROP_CANFETCHBACKWARDS.
General purpose providers may support additional functionality. It is advantageous that providers support as many extended interfaces as apply to their particular type of data.
In addition to common interface extensions, providers may expose specialized interfaces for the following sets of extended functionality:
Table 4 – Extended Interfaces
Object | Any provider | Updatable providers | Transacted providers |
DataSource | IDataSourceAdmin | ||
IDBInfo2 | |||
IPersistFile | |||
Session | IDBSchemaRowset | ITransactionLocal | |
IDBView1 | ITransactionJoin | ||
IDBCreateCommand2 | ITransactionObject | ||
IIndexDefinition | |||
ITableDefinition | |||
View1 | IViewFilter | ||
IViewSort | |||
IColumnsInfo | |||
IAccessor | |||
ISupportErrorInfo | |||
IViewRowset | |||
IViewChapter | |||
Command2 | IAccessor | ||
ICommand | |||
ICommandText | |||
IColumnsInfo | |||
ICommandPrepare | |||
IColumnsRowset | |||
ICommandProperties | |||
ICommandWithParameters | |||
IConvertType | |||
ISupportErrorInfo | |||
Command Behavior | MAXTABLESINSELECT>1 | ||
Custom Error | ISQLErrorInfo | ||
Multiple Results | IMultipleResults | ||
Rowset | IColumnsRowset | IRowsetResynch | |
IRowsetIdentity | IRowsetUpdate | ||
IRowsetLocate | |||
IChapteredRowset1 | |||
IRowsetView1 | |||
IRowsetIndex3 | |||
Rowset Behavior | DBPROP_ LITERALBOOKMARKS | DBPROP_CHANGE INSERTEDROWS | DBPROP_ COMMITPRESERVE |
DBPROP_ ORDEREDBOOKMARKS | DBPROP_RETURN PENDINGROWS | DBPROP_ ABORTPRESERVE | |
DBPROP_ LITERALIDENTITY | DBPROP_ IMMOBILEROWS | ||
DBPROP_ BOOKMARKSKIPPED | |||
DBPROP_OTHERINSERT | |||
DBPROP_ OTHERUPDATEDELETE | |||
DBPROP_ STRONGIDENTITY | |||
BLOB Support | DBPROP_OLEOBJECTS | ||
DBPROP_MULTIPLE STORAGEOBJECTS | |||
DBPROP_STRUCTURED STORAGE | |||
ISequentialStream | |||
IStream | |||
IStorage | |||
ILockBytes | |||
DBPROP_BLOCKING STORAGEOBJECTS=FALSE |
1Extended functionality that may be exposed by providers which support Rowset Processing.
2Extended functionality that may be exposed by providers which support Commands.
3Extended functionality that may be exposed by providers which support Index navigation.
Generic consumers must be prepared for providers that don't support the extended interfaces. Consumers can handle such providers in several different ways: