Creating Row Objects

A consumer obtains a row object in one of the following ways:

  • The consumer calls IOpenRowset::OpenRowset on the current session object and requests a row object instead of a rowset.

  • The consumer executes a command containing a singleton SQL SELECT statement and requests a row object instead of a rowset.

  • The consumer calls IGetRow::GetRowFromHROW on the row handle of a row in a rowset.

  • The consumer calls IBindResource::Bind or ICreateRow::CreateRow on the URL of a node in a tree-structured namespace, such as a message in a mail folder, passing DBGUID_ROW as the value of rguid.

  • The consumer calls IRow::Open on a row-object-valued column of an existing row object, passing DBGUID_ROW as the value of rguidColumnType.

  • The consumer calls IMultipleResults::GetResult and requests a row object.

Creating a Row Object with IOpenRowset

To create a row object directly with IOpenRowset, the consumer calls IOpenRowset::OpenRowset on the current session object. However, by default, IOpenRowset::OpenRowset returns a rowset object, so to obtain a row object instead of a rowset object, the consumer must do one of the following when calling IOpenRowset::OpenRowset:

  • Request one of the following interfaces that are unique to row objects: IRow, IRowChange, or IRowSchemaChange.

  • Set the rowset property DBPROP_IRow to VARIANT_TRUE by passing an appropriate DBPROPSET structure to IOpenRowset::OpenRowset through the rgPropertySets input parameter. The consumer must do this if requesting any other interface on the row object.

Creating a Row Object with a Singleton SELECT

To obtain a row object, the consumer calls IDBCreateCommand::CreateCommand on the session object to obtain a command object and then calls ICommand::Execute on the command object, requesting a row object instead of a rowset. If the command is one that returns a row, such as a singleton SQL SELECT statement, and if the provider supports creating row objects via commands, ICommand::Execute returns a row object. By default, ICommand::Execute returns a rowset object. To obtain a row object instead of a rowset object, the consumer must do one of the following when calling ICommand::Execute:

  • Request one of the following interfaces that are unique to row objects: IRow, IRowChange, or IRowSchemaChange.

  • Set the rowset property DBPROP_IRow to VARIANT_TRUE by calling ICommandProperties::SetProperties on the command object before executing the command. The consumer must do this if requesting any other interface on the row object.

OLE DB does not require providers to know the number of rows to be returned for a given SELECT statement. If the consumer has requested a row object and if the command would otherwise return a rowset of two or more rows, the provider should return only the first row (as a row object), along with a return code of DB_S_NOTSINGLETON.

Note

The "first row" is defined to be the first row of the rowset that would be returned if a rowset was requested and IRowset::GetNextRows was called with lRowsOffset set to zero. Also, it can be difficult or expensive for some providers to determine that the command would return a rowset with more than one row, so providers are not required to return DB_S_NOTSINGLETON.

Creating a Row Object from a Row in a Rowset

The consumer can obtain a row object for a row in a rowset by calling IGetRow::GetRowFromHROW on the row handle (HROW) of the row. GetRowFromHROW creates a new row object each time it is called.

Conversely, the method IRow::GetSourceRowset allows the consumer to obtain the source rowset for a row object. Row objects are permitted, but not required, to keep references on source rowsets.

Using the two methods discussed above, the consumer can navigate between a rowset and a row object.

If a row object has a source rowset and changes to this rowset are deferred, changes to all columns of the row object are also deferred. Thus, IRow::GetColumns returns the current value of all row columns, and the original values of row columns that are not part of the source rowset are unavailable. Updates to row column values, via IRowChange::SetColumns or IRowSchemaChange::AddColumns, are not propagated to the underlying data store until IRowsetUpdate::Update is called on the source rowset.

Note

IRowsetUpdate::Undo can also undo changes made to row-specific columns.

If a row object is created from a source rowset that implements IRowsetRefresh to synchronize the rowset with its data store, the row-specific column values of the row object are refreshed along with those defined by the source rowset.

Note

If a row is derived from a source rowset, changes made to a column by using the row object are visible when the column is retrieved using the source rowset. The reverse is also true; that is, changes made to a column value by using the rowset are visible when that column is accessed using the row object. If multiple row objects are created from the same HROW via calls to GetRowFromHROW, visibility to the other row objects of changes made to a specific row object is governed by properties of the source rowset such as DBPROP_OWNUPDATEDELETE.

Obtaining the URL of a Row in a Rowset

IGetRow::GetURLFromHROW can be used to obtain the URL of a row in a rowset. The consumer can then use this URL in a call to IBindResource::Bind (or IScopedOperations::Bind, if the URL represents a row in the scope of the row object on which the IScopedOperations interface was obtained) to create a new row object for this row.

In addition, DBROWCOL_ROWURL is provided as a shortcut column ID (DBID) on a row object to identify the column, if any, that contains the URL of that row. For more information about the row URL column and DBROWCOL_ROWURL, see Special Row Column DBIDs.

This topic is a part of: