Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

FIX: The Properties Collection Is Not Populated for Child Recordsets Associated with Chaptered Columns

View products that this article applies to.

This article was previously published under Q217890

↑ Back to the top


ADO Recordset objects returned from chaptered columns do not have their Properties collection populated. The Properties collection's Count property equal zero (0).
ADO extracts a child Recordset from a Hierarchical OLEDB provider by passing the value of the chaptered column to it. In the Visual Basic client code below, "rs.Fields(5)" is the chaptered column; the variable, numProps, is zero:
Dim rs As New ADODB.Recordset
Dim rsChild As ADODB.Recordset
Dim numProps As Integer
rs.Open "c:\*.*", "Provider=ChildrsProv.CHildRSProv.1", adOpenForwardOnly, adLockOptimistic

Set rsChild = rs.Fields(5).Value
numProps = rsChild.Properties.Count

↑ Back to the top


This bug was corrected in MDAC 2.1 SP2.

To work around this bug, insert the following "GetProperty()" C++ function as a method in a COM object. Essentially, the function returns the requested property of the underlying rowset using the OLE DB IDBProperties::GetPropertyInfo() and IRowsetInfo::GetProperty() methods. The parameters are:

  • pADORecordset- [in] IUnknown pointer to the Ado Recordset
  • bstrPropertyName - [in] Description of the Property ID**
  • pValue - [out] The property value
** Refer to Appendix C in the OLE DB 2.0 Programmers Reference for a comprehensive list of Property ID descriptions.
#include <COMDEF.H>
#include <oledb.h>

#undef EOF
#import "c:\program files\common files\system\ado\msado15.dll" no_namespace

_COM_SMARTPTR_TYPEDEF(IRowset, __uuidof(IRowset));
_COM_SMARTPTR_TYPEDEF(IRowsetInfo, __uuidof(IRowsetInfo));
_COM_SMARTPTR_TYPEDEF(IDBProperties, __uuidof(IDBProperties));
_COM_SMARTPTR_TYPEDEF(IGetDataSource, __uuidof(IGetDataSource));
_COM_SMARTPTR_TYPEDEF(ICommand, __uuidof(ICommand));

STDMETHODIMP CPropertyHelper::GetProperty(IUnknown *pADORecordset, BSTR bstrPropertyName, VARIANT * pValue)
	ADORecordsetConstructionPtr pRC;
	ADOConnectionConstructionPtr pCC;

	IRowsetPtr pRS;
	IRowsetInfoPtr pRI;
	IDBPropertiesPtr pDBProps;
	IGetDataSourcePtr pGetDataSource;
	ICommandPtr pCommand;
	// Make certain that we are getting an ADORecordset.
	pRC = pADORecordset;

	// Get the IRowsetInfo interface.
	pRI = pRC->GetRowset();

	// Get the property ID based on the name supplied.
	hr = pRI->GetSpecification(__uuidof(IGetDataSource), (IUnknown **)&pGetDataSource);

	// The rowset was probably created with IOpenRowset::OpenRowset,
	// but just in case...
	if (pGetDataSource.GetInterfacePtr() == NULL)
		// Need to get command first.
		hr = pRI->GetSpecification(__uuidof(ICommand), (IUnknown **)&pCommand);
		hr = pCommand->GetDBSession(__uuidof(IGetDataSource), (IUnknown **)&pGetDataSource);
	if(hr = pGetDataSource.GetInterfacePtr() == NULL)
		return  E_FAIL;
	hr = pGetDataSource->GetDataSource(__uuidof(IDBProperties), (IUnknown **)&pDBProps);
	// Want all of the rowset properties.
	PropIDSet.cPropertyIDs = 0;
	PropIDSet.guidPropertySet = DBPROPSET_ROWSETALL;
	PropIDSet.rgPropertyIDs = NULL;

	DBPROPINFOSET * pPropertyInfoSet;
	ULONG ulPropInfoSets;
	OLECHAR * pDescBuffer;
	pDBProps->GetPropertyInfo(1,&PropIDSet, &ulPropInfoSets, &pPropertyInfoSet, &pDescBuffer);
	GUID guid;
	bool bFoundProperty = false;
	// Find the ID associated with the property name.
	for(ULONG ulIndex1= 0; ulIndex1 < ulPropInfoSets && bFoundProperty ==false; ulIndex1 ++)
		for (ULONG ulIndex = 0; ulIndex < pPropertyInfoSet[ulIndex1].cPropertyInfos; ulIndex++)
			if (_wcsicmp(pPropertyInfoSet[ulIndex1].rgPropertyInfos[ulIndex].pwszDescription, bstrPropertyName) == 0)
				PropID = pPropertyInfoSet[ulIndex1].rgPropertyInfos[ulIndex].dwPropertyID;
				guid = pPropertyInfoSet[ulIndex1].guidPropertySet;
				bFoundProperty = true;

	// Free structures.

	if (bFoundProperty == false)
		return E_FAIL;  // Might also want to call CreateErrorInfor/SetErrorInfo.

	// Now use IRowsetInfo to return the property value.
	ULONG ulPropSets;
	DBPROPSET * prgPropSets;
	DBPROPIDSET	rgPropertyIDSets;

	rgPropertyIDSets.cPropertyIDs = 1;
	rgPropertyIDSets.guidPropertySet = guid; 
	rgPropertyIDSets.rgPropertyIDs = &PropID;

	hr = pRI->GetProperties(1, &rgPropertyIDSets, &ulPropSets, &prgPropSets);

	// Copy the property value to the return VARIANT.
	VariantCopy(pValue, &prgPropSets->rgProperties->vValue);
	return S_OK;

The following Visual Basic code accesses the "PropertyHelper.CPropertyHelper.1" COM object that contains the GetProperty method:
Dim rs As New ADODB.Recordset
Dim rsChild As ADODB.Recordset
rs.Open "c:\*.*", "Provider=ChildrsProv.CHildRSProv.1", adOpenForwardOnly, adLockOptimistic
Set rsChild = rs.Fields(5).Value
Dim obj
Set obj = CreateObject("PropertyHelper.CPropertyHelper.1")
Dim propVal As Variant
obj.GetProperty rsChild, "IRowsetInfo", propVal
Debug.Print propVal

↑ Back to the top


Microsoft has confirmed that this is a bug in the Microsoft products that are listed at the beginning of this article.
This problem was corrected in MDAC 2.1 SP2.

↑ Back to the top

Keywords: KB217890, kbprovider, kbmdacnosweep, kbfix, kbbug, kbado210sp2fix

↑ Back to the top

Article Info
Article ID : 217890
Revision : 2
Created on : 10/16/2002
Published on : 10/16/2002
Exists online : False
Views : 349