MDAC 2.5 SDK - OLE DB Programmer's Reference
Chapter 7: BLOBs and COM Objects
The following sections explain how consumers get and set IPersist* objects and how these objects are stored by providers.
To get an IPersist* object from a column, a consumer performs the following actions:
If the object is not currently loaded, the provider will perform the following actions:
For example, the provider might call CoCreateInstance with rclsid set to the class ID of the object and riid set to IID_IPERSISTSTORAGE. How the provider determines the class ID of the object is provider-specific.
If the provider supports only a single open storage object at a time and another storage object is open, the method returns a status of DBSTATUS_E_CANTCREATE for the column.
If the object does not support the requested interface, the method returns E_NOINTERFACE. After the method returns, the rowset does not hold any reference counts on the object.
If the object is currently loaded—which the provider can determine by virtue of the operations performed in step 4 in the preceding procedure—the provider will return a pointer to the requested interface to the consumer. If the object does not support this interface, the method returns E_NOINTERFACE.
If any errors occur during these procedures, the provider ensures that no objects remain instantiated when IRowset::GetData, IRowsetRefresh::GetLastVisibleData, or IRowsetUpdate::GetOriginalData returns.
To set an IPersist* object in a column, a consumer uses one of two procedures. The first procedure should be used only by consumers that know what kind of IPersist* objects should be stored in a column. Because the storage object, which is implemented by the rowset, does not have a pointer to the IPersist* object, the rowset cannot determine whether the IPersist* object uses a class ID that matches the class ID used by the objects in the column. The possibility therefore arises that the consumer could store an object in the column of a type that the rowset will not be able to later create an instance of.
In this first procedure, the consumer will perform the following actions:
It does this in the same way it retrieves an IStorage or IStream pointer over BLOB data. The provider does not load the object, as is the case when the consumer calls IRowset::GetData and requests a different interface, such as IPersistStorage. If the provider supports only one open storage object at a time and another storage object is open, the method returns a status of DBSTATUS_E_CANTCREATE for the column.
The consumer should be careful if it sets the pStgNew parameter to a non-null pointer, because the provider does not dissociate the column's storage object from the IPersist* object.
The second procedure can be used by any consumer. It should be used by consumers that do not know what kind of IPersist* objects can be stored in the column, because the provider can check the class ID of the object before storing it. In this second procedure, the consumer will call IRowsetChange::SetData or IRowsetChange::InsertRow and pass a pointer to an interface on the IPersist* object.
In turn, the provider will perform the following actions:
If there is an existing storage object on the column that the provider cannot release, IRowsetChange::SetData or IRowsetChange::InsertRow returns a status of DBSTATUS_E_CANTCREATE for the column. For example, this occurs if there is an IPersist* object loaded on the column. If the provider supports only one open storage object at a time and a storage object is open over another column or row, the method might return a status of DBSTATUS_E_CANTCREATE for the column.
If the provider calls IPersistStorage::Save, it sets the fSameAsLoad argument to FALSE. If the provider calls IPersistStream::Save or IPersistStreamInit::Save, it sets the fClearDirty flag to TRUE.
After IRowsetChange::SetData or IRowsetChange::InsertRow returns, the rowset does not hold any reference counts on the IPersist* object.