MDAC 2.5 SDK - Technical Articles
OLE DB defines a comprehensive set of interfaces for accessing a diverse range of data types, located in a variety of data stores. The OLE DB Programmer's Reference can be intimidating in size, but no one data store is expected to support all of the functionality defined in the reference. OLE DB data 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 predicate-based positioning if the provider doesn't support them.
Defining a minimal level of support exposed by all data stores, along with a common set of extended services, means:
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 stores expose the interfaces that reflect their native functionality. 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 multitable join is no different than navigating the result of a text file containing tabular data. Defining common interfaces in this manner allows components to more efficiently augment the individual data provider's native functionality.
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:
Table 1 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 |
Root Enumerator | IDBInitialize1 | |
IParseDisplayName1 | ||
ISourcesRowset1 | ||
Data Links | IDataInitialize1 | |
IPromptInitialize1 | ||
RowPosition | IRowPosition1 | |
DataSource | IDBCreateSession | |
IDBInitialize | ||
IDBProperties | ||
IPersist | ||
DataSource Behavior | DBPROP_INIT_PROMPT2 | |
Session | IGetDataSource | |
IOpenRowset | ||
ISessionProperties | ||
Rowset | IAccessor | IRowsetChange |
IColumnsInfo | ||
IConvertType | ||
IRowset | ||
IRowsetFind | ||
IRowsetIdentity | ||
IRowsetInfo | ||
IRowsetLocate | ||
IRowsetScroll | ||
Rowset Behavior | DBPROP_ CANHOLDROWS | DBPROP_ REMOVEDELETED |
DBPROP_ CANFETCHBACKWARDS | DBPROP_ OWNUPDATEDELETE | |
DBPROP_ CANSCROLLBACKWARDS | DBPROP_ OWNINSERT |
1 These interfaces are always supported by common components in the SDK. They are never implemented directly by providers.
2 DBPROP_INIT_PROMPT is only required if any initialization properties are required in order to connect to the provider. If calling Initialize() can succeed on a freshly created Datasource, the provider does not need to support this property.
Consumers are guaranteed to get the above functionality in one of three ways:
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.
Providers support the native functionality of the data that they expose. This includes at least the functionality described in the section "Minimum Provider Functionality" in this paper. Additional interfaces should be implemented as appropriate. If the provider natively supports all of the functionality listed in the section "Base Consumer Functionality," then service components won't be needed to provide the minimal consumer functionality. In addition, providers may expose interfaces for the extended functionality described in the section "Extended Interfaces."
All providers must be either apartment, rental, or free threaded, and must support aggregation of the DataSource, Session, and Rowset objects. If applicable, providers must support the aggregation of the Command and View objects.
Providers must support data conversions to the types returned in IColumnsInfo::GetColumnsInfo or IColumnsRowset::GetColumnsRowset for rowset columns, and ICommandWithParameters::GetParameterInfo for parameters, as well as DBTYPE_WSTR for all column or parameter values other than those described as objects. Providers that support binding to objects as IStream or ILockBytes must also support binding to those columns as ISequentialStream.
It is 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 Base application using service components to talk to a minimum provider
Table 2 Minimum Provider Interfaces
Object | Any OLE DB provider | Updatable providers |
DataSource | IDBCreateSession | |
IDBInitialize | ||
IDBProperties | ||
IPersist | ||
Session | IGetDataSource | |
IOpenRowset | ||
ISessionProperties | ||
Rowset | IAccessor | IConnectionPointContainer for IRowsetNotify1 |
IConvertType | IRowsetChange | |
IColumnsInfo | ||
IRowset | ||
IRowsetIdentity | ||
IRowsetInfo | ||
Rowset Behavior | DBPROP_CANHOLDROWS | DBPROP_ OWNUPDATEDELETE |
DBPROP_ DATASOURCEREADONLY | DBPROP_OWNINSERT | |
DBPROP_IACCESSOR | DBPROP_ REMOVEDELETED | |
DBPROP_ICOLUMNSINFO | ||
DBPROP_ICONVERTTYPE | ||
DBPROP_IROWSET | ||
DBPROP_ IROWSETIDENTITY | ||
DBPROP_IROWSETINFO |
1 Supporting IConnectionPointContainer for IRowsetNotify is not strictly required for OLE DB 2.0 providers to satisfy the minimum requirements for an updatable provider. However, updatable providers are strongly encouraged to expose this connection point as some consumers will be forced to treat providers as read-only if they do not support rowset notifications by exposing the connection point for IRowsetNotify.
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 Base application talking directly to a base provider
Providers implementing the functionality described in Table 3 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 |
Rowset | IRowsetFind | |
IRowsetLocate | ||
IRowsetScroll | ||
Rowset Behavior | DBPROP_ CANSCROLLBACKWARDS1 | |
DBPROP_ CANFETCHBACKWARDS1 |
1 Providers 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 | IConnectionPointContainer for IDBAsynchNotify | ||
IDBAsynchStatus | |||
IDataSourceAdmin | |||
IDBInfo2 | |||
IPersistFile | |||
ISupportErrorInfo | |||
Session | IAlterIndex | ITransactionLocal | |
IAlterTable | ITransactionJoin | ||
IDBSchemaRowset | ITransactionObject | ||
IDBView1 | |||
IDBCreateCommand2 | |||
IIndexDefinition | |||
ITableDefinition | |||
ISupportErrorInfo | |||
View1 | IViewFilter | ||
IViewSort | |||
IColumnsInfo | |||
IAccessor | |||
ISupportErrorInfo | |||
IViewRowset | |||
IViewChapter | |||
Command2 | IAccessor | ||
ICommand | |||
ICommandPersist | |||
ICommandText | |||
IColumnsInfo | |||
ICommandPrepare | |||
IColumnsRowset | |||
ICommandProperties | |||
ICommandWithParameters | |||
IConvertType | |||
ISupportErrorInfo | |||
Command Behavior | MAXTABLESINSELECT>1 | ||
Custom Error | ISQLErrorInfo | ||
Multiple Results | IMultipleResults | ||
Rowset | IConnectionPointContainer for
-IRowsetNotify -IDBAsynchNotify |
IRowsetResynch | |
IColumnsRowset | |||
IChapteredRowset1 | |||
IDBAsynchStatus | IRowsetUpdate | ||
IRowsetChapterMember | |||
IRowsetIdentity | |||
IRowsetLocate | |||
IRowsetView1 | |||
IRowsetIndex3 | |||
IRowsetIndex3 | |||
ISupportErrorInfo | |||
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 |
1 Extended functionality that may be exposed by providers which support rowset processing.
2 Extended functionality that may be exposed by providers which support commands.
3 Extended 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: