Storage Objects and Rowset Update Semantics

When does the data set in a storage object become visible to other transactions operating at the Read Uncommitted isolation level? For providers built over database servers, this question can also be phrased as, "When does data set in a storage object become visible at the data source?"

The rules for storage objects are similar to the rules for data in other columns. That is, if the rowset is in immediate update mode, data made available to the rowset is immediately made available to Read Uncommitted transactions. If the rowset is in delayed update mode, data made available to the rowset is not made available to Read Uncommitted transactions until the consumer calls IRowsetUpdate::Update.

However, storage objects differ in two ways from other, nonstorage columns in the rowset:

Storage object boundary controls

The following table shows the sequence of calls needed to make data set in a storage object visible to other transactions operating at the Read Uncommitted isolation level. In this table, Write refers collectively to any method on a storage interface that sets data, such as ISequentialStream::Write, IStream::Write, or ILockBytes::WriteAt, and SetData refers collectively to IRowsetChange::SetData and IRowsetChange::InsertRow. ILockBytes storage objects are always in Direct mode.

Call sequence required for storage object visibility


Storage mode

Update mode
DBPROP_DELAY
STORAGEOBJECTS
Calls needed to expose data to other transactions running at Read Uncommitted
Direct Immediate Not applicable Write
 – or – 
SetData
Direct Delayed VARIANT_FALSE Write
 – or – 
SetData
Direct Delayed VARIANT_TRUE Write
Update
 – or – 
SetData
Update
Transacted Immediate Not applicable Write
Commit on storage interface
 – or – 
SetData
Transacted Delayed VARIANT_FALSE Write
Commit on storage interface
 – or – 
SetData
Transacted Delayed VARIANT_TRUE Write
Commit on storage interface
Update
 – or – 
SetData
Update

When the rowset is in delayed update mode, the consumer cannot undo any pending changes made through a storage object if that object is still open. That is, if the provider creates a storage object over the BLOB and returns a pointer to it through IRowset::GetData, the consumer must release this storage object before calling IRowsetUpdate::Undo. If the consumer fails to release the storage object, Undo returns a status of DBROWSTATUS_E_OBJECTOPEN for the row.