BLOBs as Storage Objects

When a BLOB is treated as a storage object, you can get or set it in pieces using ISequentialStream, IStream, IStorage, or ILockBytes, collectively known as the storage interfaces. The rowset acts as a factory for the objects that expose these interfaces, which are collectively known as storage objects.

The rows in the rowset act as containers of the storage objects. The relationship between a storage object and the row that contains it is the same as the relationship between an IStream or IStorage object and its parent IStorage object.

This relationship dictates the behavior of the storage object with respect to its containing row in many circumstances. For example, the Structured Storage specification states that, when a parent IStorage is released, all child IStorage and IStream objects are invalidated. Similarly, if a row handle is released with IRowset::ReleaseRows, any storage objects open in that row enter a zombie state, where releasing the object generally is the only valid consumer action. Any questions not specifically answered in this specification about the relationship between rows and storage objects can be answered by looking at the Structured Storage specification.

The following table shows the rowset methods and interfaces that are analogous to IStorage methods and modes.

Analogous methods, modes, and interfaces for IStorage and IRowset

IStorage method or mode Rowset method or interface
Transacted mode Delayed update mode
Direct mode Immediate update mode
IStorage::Commit IRowsetUpdate::Update
IStorage::Revert IRowsetUpdate::Undo
IStorage::CreateStream, IStorage::OpenStream, IStorage::CreateStorage, IStorage::OpenStorage IRowset::GetData

By default, BLOB columns are deferred. In most cases, their data is not fetched and storage objects are not created until GetData is called. Methods that fetch rows, such as IRowset::GetNextRows, do not usually return data for BLOB columns in the rowset's copy of the row.

For more information, see "Getting and Setting BLOB Data with Storage Objects" later in this chapter and "Deferred Columns" in Chapter 4.

IStorage::DestroyElement IRowsetChange::SetData. For more information, see "Getting and Setting BLOB Data with Storage Objects," later in this chapter.

The only significant difference between a parent IStorage object in the Structured Storage model and a row in a rowset is that a row can contain a storage object that exposes ISequentialStream, IStream, IStorage, or ILockBytes, whereas a parent IStorage object can expose only a child that exposes IStorage or IStream. For purposes of the analogy between Structured Storage and rows, ISequentialStream and ILockBytes storage objects are usually treated as IStream storage objects.