MDAC 2.5 SDK - OLE DB Providers
OLE DB Provider for SQL Server


 

Fetching Rows

The IRowset interface is the base rowset interface. It provides methods for fetching rows sequentially, getting the data from those rows, and managing rows. Consumers use the methods in IRowset for all basic rowset operations, including fetching and releasing rows and getting column values.

When a consumer gets an interface pointer on a rowset, usually the first step is to determine the capabilities of the rowset by using the IRowsetInfo::GetProperties method. This returns information about the interfaces exposed by the rowset as well as capabilities of the rowset that do not show up as distinct interfaces, such as the maximum number of active rows and how many rows can have pending updates at the same time.

The next step for consumers is to determine the characteristics, or metadata, of the columns in the rowset. For this they use the IColumnsInfo or IColumnsRowset methods, for simple or extended column information, respectively. IColumnsInfo::GetColumnInfo returns the following:

The consumer determines which columns it needs, either from the metadata or on the basis of the text command that generated the rowset. It determines the ordinals of the needed columns from the ordering of the column information returned by IColumnsInfo or from the ordinals in the column metadata rowset returned by IColumnsRowset.

The ordinals are used to specify a binding to a column. A binding is a structure that associates an element of the consumer's structure with a column. The binding can bind the data value, length, and status value of the column.

A set of bindings is gathered together in an accessor, which is created with the IAccessor::CreateAccessor method. An accessor can contain multiple bindings so that the data for multiple columns can be retrieved or set in a single call. The consumer can create several accessors to match different usage patterns in different parts of the application. It can create and release accessors at any time while the rowset remains in existence.

To fetch rows from the database, the consumer calls a method, such as IRowset::GetNextRows or IRowsetLocate::GetRowsAt. These fetch operations put row data from the server into the row buffer of the provider. The consumer does not have direct access to the row buffer of the provider. The consumer uses IRowset::GetData to copy data from the buffer of the provider to the consumer buffer and IRowsetChange::SetData to copy data changes from the consumer buffer to the provider buffer.

The consumer calls the IRowset::GetData method and passes it the handle to a row, the handle to an accessor, and a pointer to a consumer-allocated buffer. GetData converts the data and returns the columns as specified in the bindings used to create the accessor. The consumer can call IRowset::GetData more than once for a row, using different accessors and buffers; therefore, the consumer can have multiple copies of the same data.

Data from variable-length columns can be treated several ways. First, such columns can be bound to a finite section of the consumer's structure, which causes truncation when the length of the data exceeds the length of the buffer. The consumer can determine that truncation has occurred by checking for the status DBSTATUS_S_TRUNCATED. The returned length is always the true length in bytes, so the consumer also can determine how much data was truncated.

When the consumer is finished fetching or updating rows, it releases them with the IRowset::ReleaseRows method. This releases resources from the copy of the rows in the rowset and makes room for new rows. The consumer can then repeat its cycle of fetching or creating rows and accessing the data in them.

When the consumer is done with the rowset, it calls the IAccessor::ReleaseAccessor method to release any accessor. It calls the IUnknown::Release method on all interfaces exposed by the rowset to release the rowset. When the rowset is released, it forces the release of any remaining rows or accessors the consumer may hold.