Share via


OLE DB Minimum Levels of Consumer and Provider Functionality

 

Microsoft Corporation

Summary: OLE DB defines a comprehensive set of interfaces for accessing a diverse range of data types located in a variety of relational and nonrelational data stores. OLE DB data providers need to expose only the minimum number of interfaces that reflect the natural functionality of their data stores. This makes OLE DB providers much easier to write. Above that minimal level, common OLE DB service components provide interoperability through generic implementations of extensions such as scrolling or predicate-based positioning. This means that applications consuming OLE DB, directly or through ADO, can achieve a richer level of functionality because the OLE DB service components offer extended functionality that is not necessarily provided by the data store.

Contents

Introduction: OLE DB as a Component Technology Consumers Providers

Introduction: OLE DB as a Component Technology

The purpose of this article is to define the minimal levels of functionality that an OLE DB consumer should expect from a general-purpose OLE DB provider. It describes two levels of functionality. One is the base level, which represents the most basic level of functionality that will enable very simple data transfer between providers and consumers. The other level is the extended level, which represents a higher, value-added level of functionality that most general-purpose providers will want to provide for most common data consumer applications.

The key to making this work is to separate the most essential functions from the more sophisticated functions. This is possible because OLE DB is designed as a component-based technology, building on the framework established by Microsoft's Component Object Model (COM). In COM, an interface is used to collect a group of functions. COM clearly defines the expected behavior of components when requested interfaces are not implemented. In COM, only the IUnknown interface must be implemented. All other interfaces are optional.

This design makes a few very important features possible. Components can be designed to interact correctly at different levels of functionality without limiting new features or requiring an all-or-nothing implementation. Additionally, multiple components can be combined in a seamless fashion, which reduces the work needed to achieve an advanced level of functionality. A component, by supporting aggregration, can appear to inherit interfaces from another component without actually knowing anything about that other component.

As COM components, OLE DB components also allow optional levels of functionality. The OLE DB Programmer's Reference describes all the possible interfaces, and the resulting levels of functionality, that OLE DB developers can use. However, only some of these interfaces are needed for the most basic functionality, and this article identifies those interfaces. Any other interfaces defined by the OLE DB Programmer's Reference are completely optional, and it is the developer's discretion whether to implement them.

Consumers and Providers

OLE DB describes the relationship between two components by labeling one component a data provider and the other a consumer. Even though a single component can be both a data provider and a consumer, what is important is the relationship between two components, and in such cases one component is always acting in the role of the data provider and the other as the consumer.

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. Therefore, because data providers have different functionality, it's important not to limit that functionality. However, not all providers should be expected to expose simple tabular data to implement a full-blown query engine. A general-purpose provider exhibits a minimal level of functionality that most consumers can use, regardless of the source of data.

Implementing this minimum level does not limit a provider's ability to expose interfaces that are specific to the type of data it can access. All OLE DB providers, regardless of their level of functionality, have the ability to expose any OLE DB object or interface that the developer thinks is important to the design of the provider.

Note

   

Custom COM interfaces that are not part of the OLE DB provider specification should not be implemented. Instead, any features that are unique to a provider should be exposed through OLE DB properties and objects. An OLE DB provider that exposes custom COM interfaces will cause it to be tightly coupled to any consumer that uses those interfaces. A design using proprietary COM interfaces contradicts one of the primary goals of OLE DB: to keep the methods used to access data consistent across all providers. To keep training costs and code complexity low, developers writing OLE DB consumers prefer to work with standardized data access techniques.

Consumers

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 specific to that provider, such as its ability to update data or its dynamic properties. Consumers may also be written to consume generic providers. This article focuses on the features these generic providers should have. From the consumer's perspective, there are two levels of functionality for generic OLE DB providers: base, and extended. To consume generic providers, the consumer can choose from a range of strategies, such as the following:

  • Consume a base level of functionality and work with all OLE DB providers.
  • Consume an extended level of functionality and query the provider for support of extended functionality.
  • Consume an extended level of functionality and invoke service components to implement missing functionality.

Generic consumers must be prepared for providers that don't support the extended interfaces. Consumers can handle such providers in the following ways:

  • The consumer can invoke common services to implement extended functionality, where such service components are available.
  • The consumer can implement extra code within the application to compensate for missing functionality.
  • The consumer can reduce the functionality available to the user based on missing functionality in the provider.
  • The consumer can return an error indicating that the provider is not capable of supporting required functionality.

The following section describes the entire base level of functionality that all generic consumers can expect all generic OLE DB providers to support. In some cases, OLE DB service components implement the functionality rather than the OLE DB providers.

Required Consumer Objects and Interfaces

The following objects and their respective interfaces are always required. Some interfaces and the properties they support are available only if the OLE DB provider supports updating data. If the OLE DB provider does not support these optional interfaces, the provider should be considered a read-only provider.

Root Enumerator Object

The following interfaces for this object are always supported by common components in OLE DB. They are never implemented directly by providers.

IDBInitialize

IParseDisplayName

ISourcesRowset

Data Links Object

The following required interfaces for this object are always supported by common components in OLE DB. They are never implemented directly by providers.

IDataInitialize

IPromptInitialize

Row Position Object

The following required interface for this object is always supported by common components in OLE DB. It is never implemented directly by providers.

IRowPosition

Data Source Object

The following interfaces are required for this object:

IDBCreateSession

IDBInitialize

IDBProperties (see "Required Consumer Properties," below)

IPersist

Session Object

IGetDataSource

IOpenRowset

ISessionProperties

Rowset Object

The following interfaces are required for this object:

IAccessor

IColumnsInfo

IConvertType

IRowset

IRowsetChange (required for updatable providers only)

IRowsetFind

IRowsetIdentity

IRowsetInfo (see "Required Consumer Properties," below)

IRowsetLocate

IRowsetScroll

Required Consumer Properties

Some objects support interfaces that expose dynamic properties for the object. This section lists all the properties that a consumer can expect all OLE DB providers to support at the base level of functionality.

Some properties are available only if the OLE DB provider supports updating data. If the OLE DB provider does not support these optional properties, it should be considered a read-only provider.

IDBProperties Interface

This interface must support the following property:

DBPROP_INIT_PROMPT

The DBPROP_INIT_PROMPT property has a special condition. Support for DBPROP_INIT_PROMPT is required only if any initialization properties are required for connecting to the provider. If calling IDBInitialize::Initialize can succeed on a freshly created data source object, the provider does not need to support this property.

A limited exception to this requirement may be made in specific circumstances. Some providers may require initialization properties for IDBInitialize::Initialize to succeed but for some specific reason, such as memory or user interface requirements, cannot prompt the user. In such a case, the correct action is for the provider to support only the DBPROMPT_NOPROMPT value for the DBPROP_INIT_PROMPT property. This behavior does not bring the provider to the minimum level of functionality and should be used only for exceptional cases. The documentation for the provider should clearly document this exception as well as the actual behavior of the provider when given a value other than DBPROMPT_NOPROMPT. The suggested behavior is that setting DBPROP_INIT_PROMPT to values other than DBPROMPT_NOPROMPT should cause either a DB_S_ERRORSOCCURRED or a DB_E_ERRORSOCCURRED result, with the DBPROPSTATUS value for the DBPROP_INIT_PROMPT property set to DBPROPSTATUS_NOTSUPPORTED.

IRowsetInfo Interface

This interface must support the following properties:

DBPROP_CANFETCHBACKWARDS

DBPROP_CANHOLDROWS

DBPROP_CANSCROLLBACKWARDS

DBPROP_OWNINSERT (for updatable providers)

DBPROP_OWNUPDATEDELETE (for updatable providers)

DBPROP_REMOVEDELETED (for updatable providers)

Providers

Developers of general-purpose OLE DB providers must offer consumers at least the base level of functionality. There are two ways to achieve this. One way is to write the provider to a minimum level and rely upon OLE DB service components to complete the functionality to the base level. The other way is to write the provider to implement the base level of functionality entirely and not use the OLE DB service components.

The levels discussed in the sections that follow are minimal levels. Additional interfaces can always be implemented wherever the developer of the OLE DB provider sees fit. The extended level of functionality represents the level that most common general-purpose OLE DB providers will have.

Data providers written in Microsoft® Visual Basic®, Microsoft Visual J++®, Microsoft Visual C++®, or C, using the OLE DB Simple Provider (OSP) Toolkit, automatically support all of the base level of functionality and more.

General Behavior

All providers must be apartment, rental, or free threaded and must support aggregation of the data source, 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.

Minimum Level Providers

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 objects, interfaces, and behavior listed in this section to be considered a generic OLE DB provider. Providers implementing the minimum provider functionality can rely on OLE DB service components available in the Microsoft Data Access Components (MDAC) 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

Required Provider Objects and Interfaces

OLE DB providers at the minimum level of functionality must support the following objects and their interfaces. Some interfaces are required only for OLE DB providers that support updating data. Providers that do not support these interfaces are considered read-only providers.

Note

   

Supporting an interface means supporting all methods within that interface. No methods return E_NOTIMPL.

Data Source Object

The following interfaces are required for this object:

IDBCreateSession

IDBInitialize

IDBProperties

IPersist

Session Object

The following interfaces are required for this object:

IGetDataSource

IOpenRowset

ISessionProperties

Rowset Object

The following interfaces are required for this object:

IAccessor

IColumnsInfo

IConnectionPointContainer for IRowsetNotify (for updatable providers)

IConvertType(for updatable providers)

IRowset

IRowsetChange (for updatable providers)

IRowsetIdentity

IRowsetInfo (see "Required Provider Properties," below)

Supporting IConnectionPointContainer for IRowsetNotify is not strictly required for OLE DB providers to satisfy the minimum requirements for an updatable provider. However, updatable providers are strongly encouraged to expose this connection point because 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.

Required Provider Properties

Some objects support interfaces that expose dynamic properties for the object. This section lists all the properties that all OLE DB providers must support at the minimum level of functionality.

Some properties are required only if the OLE DB provider supports updating data. If the OLE DB provider does not support these optional properties, the provider will be considered a read-only provider.

IRowsetInfo Interface

This interface must support the following properties:

DBPROP_CANHOLDROWS

DBPROP_DATASOURCEREADONLY

DBPROP_IACCESSOR

DBPROP_ICOLUMNSINFO

DBPROP_ICONVERTTYPE

DBPROP_IROWSET

DBPROP_IROWSETIDENTITY

DBPROP_IROWSETINFO

DBPROP_OWNINSERT (for updatable providers)

DBPROP_OWNUPDATEDELETE (for updatable providers)

DBPROP_REMOVEDELETED (for updatable providers)

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 user has not requested the property.

Base Level Providers

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

Required Objects and Interfaces for Base Level Provider Implementation

OLE DB providers at the base level of functionality must support the following objects and their interfaces. Some interfaces are required only for OLE DB providers that support updating data. Providers that do not support these interfaces are considered read-only providers.

Supporting an interface means supporting all methods within that interface. No methods return E_NOTIMPL.

Rowset Object

The following interfaces are required for this object:

IRowsetFind

IRowsetLocate

IRowsetScroll

Required Properties for Base Level Provider Implementation

Some objects support interfaces that expose dynamic properties for the object. This section lists all the properties that all OLE DB providers must support at the base level of functionality.

Some properties are required only if the OLE DB provider supports updating data. If the OLE DB provider does not support these optional properties, the provider will be considered a read-only provider.

IRowsetInfo Interface

This interface must support the following properties:

DBPROP_CANFETCHBACKWARDS

DBPROP_CANSCROLLBACKWARDS

Providers that support the property DBPROP_CANSCROLLBACKWARDS must also support the property DBPROP_CANFETCHBACKWARDS.

Extended Level Providers

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:

  • Rowset processing—Exposed by providers that support native filter or sort capabilities.
  • Commands—Exposed by providers that can execute more sophisticated queries or statements.
  • Transactions—Exposed by providers that can support transactional capabilities.
  • Index navigation—Exposed by providers built on indexed data to expose index functionality to service components such as query processors. OLE DB consumers other than service components generally do not directly consume these interfaces.

Required Objects and Interfaces for Extended Level Provider Implementation

OLE DB providers at the extended level of functionality must support the following objects and their interfaces. Some interfaces are required only for OLE DB providers that support updating data. Providers that do not support these interfaces are considered read-only providers.

Note

   

Supporting an interface means supporting all methods within that interface. No methods return E_NOTIMPL.

Data Source Object

The following interfaces are required for this object:

IConnectionPointContainer for IDBAsynchNotify

IDBAsynchStatus

IDataSourceAdmin

IDBInfo (extended functionality that may be exposed by providers that support rowset processing; see "Required Properties for Extended Level Provider Implementation," below)

IPersistFile

ISupportErrorInfo

Session Object

The following interfaces are required for this object:

IAlterIndex

IAlterTable

IDBCreateCommand (extended functionality that may be exposed by providers that support commands)

IDBSchemaRowset

IDBView (extended functionality that may be exposed by providers that support rowset processing)

IIndexDefinition

ISupportErrorInfo

ITableDefinition

ITransactionJoin (for transacted providers)

ITransactionLocal (for transacted providers)

ITransactionObject (for transacted providers)

View Object

The view object, available through the IDBView interface, represents extended functionality that may be exposed by providers that support rowset processing. The following interfaces are required for this object:

IAccessor

IColumnsInfo

ISupportErrorInfo

IViewChapter

IViewFilter

IViewRowset

IViewSort

Command Object

The command object, available through the IDBCreateCommand interface, represents extended functionality that may be exposed by providers that support commands. The following interfaces are required for this object:

IAccessor

IColumnsInfo

IColumnsRowset

ICommand

ICommandPersist

ICommandPrepare

ICommandProperties (see "Required Properties for Extended Level Provider Implementation," below)

ICommandText

ICommandWithParameters

IConvertType

ISupportErrorInfo

Custom Error Object

The following interface is required for this object:

ISQLErrorInfo

Multiple Results Object

The following interface is required for this object:

IMultipleResults

Rowset Object

The following interfaces are required for this object:

IChapteredRowset (extended functionality that may be exposed by providers that support rowset processing)

IColumnsRowset

IConnectionPointContainer for IDBAsynchNotify

IConnectionPointContainer for IRowsetNotify

IDBAsynchStatus

IRowsetChapterMember

IRowsetIdentity

IRowsetIndex (extended functionality that may be exposed by providers that support index navigation)

IRowsetLocate

IRowsetResynch (for updatable providers)

IRowsetUpdate (for updatable providers)

IRowsetView (extended functionality that may be exposed by providers that support rowset processing)

ISupportErrorInfo

BLOB Support

The following interfaces are required for this object (applies to rowset objects):

ILockBytes

ISequentialStream

IStorage

IStream

Required Properties for Extended Level Provider Implementation

Some objects support interfaces that expose dynamic properties for the object. This section lists all the properties that all OLE DB providers must support at the extended level of functionality.

Some properties are required only if the OLE DB provider supports updating data. If the OLE DB provider does not support these optional properties, the provider will be considered a read-only provider.

ICommandProperties Interface

This interface must support the following property:

DBPROP_MAXTABLESINSELECT > 1

IRowsetInfo Interface

This interface must support the following properties:

DBPROP_ABORTPRESERVE (for transacted providers)

DBPROP_BOOKMARKSKIPPED

DBPROP_CHANGEINSERTEDROWS (for updatable providers)

DBPROP_COMMITPRESERVE (for transacted providers)

DBPROP_IMMOBILEROWS (for updatable providers)

DBPROP_LITERALBOOKMARKS

DBPROP_LITERALIDENTITY

DBPROP_ORDEREDBOOKMARKS

DBPROP_OTHERINSERT

DBPROP_OTHERUPDATEDELETE

DBPROP_RETURNPENDINGROWS (for updatable providers)

DBPROP_STRONGIDENTITY

BLOB Support

BLOBs must support the following properties (applies to IRowset interface on rowset objects):

DBPROP_BLOCKING STORAGEOBJECTS = FALSE

DBPROP_MULTIPLE STORAGEOBJECTS

DBPROP_OLEOBJECTS

DBPROP_STRUCTURED STORAGE