Enumerating Data Sources and Enumerators

Generic consumers should use enumerators to search for data sources and other enumerators, rather than searching the registry directly. In this way, consumers will continue to work if the registry information changes or new root enumerators with additional functionality, such as the ability to enumerate data sources on other machines, are later introduced. To create an enumerator, the consumer calls CoCreateInstance with the class ID of the enumerator. In most cases, the consumer requests ISourcesRowset when creating an enumerator.

To list the data sources and enumerators visible to the current enumerator, the consumer calls ISourcesRowset::GetSourcesRowset. This method returns a rowset of information about the currently visible data sources and enumerators. To create an instance of a data source or enumerator listed in this rowset, the consumer first calls IParseDisplayName::ParseDisplayName for the returned display name. This method returns a moniker, which is the name of the object instance. The consumer can then bind to create an instance of the object.

Each row in the rowset returned by ISourcesRowset contains a SOURCES_ISPARENT column. For enumerator rows, this column contains VARIANT_TRUE if the enumerator described by the row is the same one that can enumerate the current one. For example, if the enumerator lists files and directories in the file system, this is the parent directory. The SOURCES_ISPARENT column thus allows the consumer to traverse backward through a hierarchy of enumerators, such as might be found over a file system. The consumer ignores the SOURCES_ISPARENT column for data source rows.

A root enumerator is shipped in the OLE DB Software Development Kit (SDK). This enumerator traverses the registry searching for providers and enumerators. It has a class ID of CLSID_OLEDB_ENUMERATOR. For more information about it, see the "Root Enumerator Object" in the OLE DB Core Components documentation.

Providers also can support enumerators, although they are not required to do so. These enumerators search for data sources and enumerators known to the provider. For example, suppose a provider exposes data in an SQL DBMS that supports multiple, separate databases in a single installation where the DBMS treats each database as a separate data source. The enumerator for this provider might search the DBMS for databases. The rowset returned by the enumerator would include one row for each database it finds, marking that database as a data source.

Or suppose a provider exposes data in text files and treats each directory as a data source and each text file in that directory as a table. The enumerator for this provider might traverse the file system. The rowset returned by the enumerator would include two rows for each directory it finds, marking one row as a data source and the other row as an enumerator. To access the files in a directory, the consumer would create an instance of a data source object over the directory, using the display name from the row marked as a data source. To search for subdirectories, the consumer would create an instance of an enumerator over the directory, using the display name from the row marked as an enumerator.

For information about the registry entries used by enumerators, see "Enumerator Registry Entries" in Chapter 14.