IRowsetNotify

IRowsetNotify is the callback interface that a consumer must support to connect to local notifications provided by a rowset object. The notifications are intended to synchronize objects that are attached to the same rowset instance. The notifications do not reflect changes in underlying shared tables that occur through other programs or users.

The notifications use the standard COM connection point scheme for operations or events on rowset objects. A rowset object supports IConnectionPointContainer, and the consumer calls FindConnectionPoint for IID_IRowsetNotify to obtain the correct IConnectionPoint interface. The consumer then advises that connection point to connect and supplies a pointer to the consumer's IRowsetNotify interface.

Providers are required to support all notifications for which they have the underlying functionality.

For more information about notifications, see OLE DB Object Notifications.

When to Implement

IRowsetNotify is implemented by consumers that require notification. If the command requests support for IConnectionPointContainer, the rowset object is required to support a connection point for IRowsetNotify. Providers should implement this connection point if they expect to work directly with general-purpose consumers.

Notification about transactions is not handled through rowset objects. There may be multiple rowsets for each transaction, leading to a flood of events. Consumers that need to be notified of transaction activity should connect to the transaction coordinator. For more information, see Event Notifications.

IRowset is a prerequisite for notification.

DBEVENTPHASE

Notifications have multiple phases. The provider uses the IRowsetNotify callback method for every phase of the notification. A phase describes the state of the notification as the provider and consumer signal intent, approval, rejection, or completion of the change. The phases are similar to phases in a two-phase transaction commit protocol because the problem of ensuring that all controls authorize and succeed in handling an event or action on a rowset is very similar to the problem of ensuring that all resource managers agree to, and succeed in, committing a transaction.

In OLE DB, phases are enumerated by DBEVENTPHASE values, as listed in the following table. In the descriptions, all consumer objects that connect their IRowsetNotify interface to the rowset object are the listeners.

Value

Description

DBEVENTPHASE_OKTODO

Informs a listener of an impending event. All listeners must return S_OK from DBEVENTPHASE_OKTODO for the event to proceed. Any listener can cancel the impending event (DBREASON) by returning S_FALSE. The listener can prepare for the event but should do nothing irreversible or time consuming.

If a listener cancels the event (DBREASON) by returning S_FALSE, all listeners that have already been called will be called again with DBEVENTPHASE_FAILEDTODO..

DBEVENTPHASE_ABOUTTODO

Informs a listener that DBEVENTPHASE_OKTODO has been approved and that all listeners can proceed to final preparations, which must be reversible but which may be lengthy. The listener should cancel this phase only if it is stopped by an error; it should have cleared all logical objections at the earlier DBEVENTPHASE_OKTODO phase.

If a listener cancels the event (DBREASON) by returning S_FALSE, all listeners that have already been called will be called again with DBEVENTPHASE_FAILEDTODO..

DBEVENTPHASE_SYNCHAFTER

Informs a listener that the event has occurred after the rowset object's copy of the row has been modified but before the data store has received the change. The listener can synchronize itself with the rowset and ensure that it has no physical reason not to agree to commit the changes.

If a listener cancels the event (DBREASON) by returning S_FALSE, all listeners that have already been called will be called again with DBEVENTPHASE_FAILEDTODO.

DBEVENTPHASE_FAILEDTODO

Informs a listener that has previously been called for this event that the action on the rowset object has failed. The listener should reverse all changes and synchronize with the state of the rowset.

DBEVENTPHASE_DIDEVENT

Informs a listener that all consumers have synchronized themselves and agreed to commit the changes. The listener should now commit its changes.

The final phase of a notification is always either DBEVENTPHASE_FAILEDTODO or DBEVENTPHASE_DIDEVENT. If there are no phases, it is equivalent to DBEVENTPHASE_DIDEVENT.

All providers must support the DBEVENTPHASE_FAILEDTODO and DBEVENTPHASE_DIDEVENT phases. Whether providers support DBEVENTPHASE_OKTODO, DBEVENTPHASE_ABOUTTODO, and DBEVENTPHASE_SYNCHAFTER is provider specific, although all but the simplest providers support these phases. To determine which phases a provider supports, a consumer calls IDBProperties::GetProperties for the DBPROP_NOTIFICATIONPHASES property.

If a method operates on multiple rows and generates a single-phased notification, such as DBREASON_ROW_ACTIVATE or DBREASON_ROW_RELEASE, the provider makes a single call to IRowsetNotify::OnRowChange and passes an array containing the handles of all of the affected rows.

If a method operates on multiple rows and generates multi-phased notifications, such as DBREASON_ROW_UPDATE or DBREASON_ROW_UNDOCHANGE, the number of calls to IRowsetNotify::OnRowChange for each phase depends on the DBPROP_NOTIFICATIONGRANULARITY property.

It is provider-specific whether or not listeners who register after some but not all of the phases of an event have been fired are called for the remaining phases. A listener must be prepared to get only the final phases of an event when registering for notifications on an object that is in the midst of sending notifications.

DBREASON

Reasons are types of events or "fine-tunings" of the notifications generated by events on rowset objects. The receiver of notifications is expected to care only about the general effect of the event, but there may be other effects that more specialized consumers need to know about. The DBEVENTPHASE represents the basic state of the event, and the DBREASON is a reason for the event.

Providers are required to support all DBREASONs for which they have the underlying functionality. IRowsetNotify methods must return S_OK or DB_S_UNWANTEDREASON when they receive a DBREASON value they do not recognize. Providers are not expected to add new DBREASONs to the defined set. Providers defining new DBREASONs should do so through an entirely new notification interface with its own IID.

The values described in the following table are valid for DBREASON.

Value

Description

DBREASON_ROW_ASYNCHINSERT

The rowset is being randomly asynchronously populated, and one or more rows have been inserted. Only the DBEVENTPHASE_DIDEVENT phase occurs.

For more information, see Asynchronous Rowset Population.

DBREASON_ROWSET_FETCHPOSITIONCHANGE

The next fetch position changed as a result of a call to IRowset::GetNextRows or IRowset::RestartPosition. All phases can occur.

DBREASON_ROWSET_RELEASE

The rowset is being released; that is, its reference count is zero. Only the DBEVENTPHASE_DIDEVENT phase occurs. The rowset no longer exists when the notification for this DBREASON is sent out, so recipients must not make any calls upon it. In COM, there is no way to deny permission to IUnknown::Release.

DBREASON_ROWSET_CHANGED

The rowset metadata has changed.

Pointers to interfaces on the rowset remain valid.

Providers must revalidate accessors against the metadata, and this might fail due to the changes in the metadata. For example, the accessor might now specify an unsupported conversion.

Consumers should free any held row handles when a notification with this DBREASON is generated, because handles to rows are likely to have become invalid. For example, IRowset::GetData might return DB_E_BADROWHANDLE, or IRowsetUpdate::Update might return DBROWSTATUS_E_INVALID. The result of passing such a row handle is provider-specific, although the provider cannot terminate abnormally.

Only the DBEVENTPHASE_DIDEVENT phase occurs.

DBREASON_COLUMN_SET

A column value is set. All phases can occur.

DBREASON_COLUMN_RECALCULATED

A calculated column takes a new value because its input columns change. Only the DBEVENTPHASE_DIDEVENT phase occurs.

DBREASON_ROW_ACTIVATE

A function, such as IRowset::GetNextRows or IRowsetLocate::GetRowsAt, caused a new set of rows to be fetched. Only the DBEVENTPHASE_DIDEVENT phase occurs. For best results, the provider should send this reason for newly fetched rows only, but it might be expensive for providers to determine whether or not a row is newly fetched.

DBREASON_ROW_RELEASE

IRowset::ReleaseRows was called, and the row's reference count is zero. The array of row handles the provider passed to the listeners is the subset of the original array of row handles passed to ReleaseRows ? that is, those row handles for which the reference count is zero. Only the DBEVENTPHASE_DIDEVENT phase occurs. The returned row handles might be invalid and therefore should not be used with any methods.

DBREASON_ROW_DELETE

IRowsetChange::DeleteRows has been called. All phases can occur.

DBREASON_ROW_FIRSTCHANGE

The first time any column in the row is set, this notification occurs. It precedes DBREASON_COLUMN_SET. All phases can occur. This reason occurs only when the rowset is in delayed update mode. It occurs the first time a column in a row is modified after the row was fetched or after the last call to IRowsetUpdate::Update or IRowsetUpdate::Undo, whichever is more recent.

DBREASON_ROW_INSERT

IRowsetChange::InsertRowhas been called. All phases can occur.

DBREASON_ROW_RESYNCH

IRowsetRefresh::RefreshVisibleData has been called. All phases can occur.

DBREASON_ROW_UNDOCHANGE

IRowsetUpdate::Undo has been called on a pending change row. All phases can occur.

DBREASON_ROW_UNDOINSERT

IRowsetUpdate::Undo has been called on a pending insert row. All phases can occur.

DBREASON_ROW_UNDODELETE

IRowsetUpdate::Undo has been called on a pending delete row. All phases can occur.

DBREASON_ROW_UPDATE

IRowsetUpdate::Update has been called on a row with a pending change. All phases can occur.

The following table lists all rowset methods, the DBREASON values they generate, and the phases for each reason. Nested notifications occur when the consumer calls another rowset method while processing a notification.

Method

DBREASON generated [1]

Phases

IUnknown::AddRef

None

N/A

IUnknown::QueryInterface

None

N/A

IUnknown::Release

_ROWSET_RELEASE

DIDEVENT

ICommand::Execute

_ROW_ASYNCINSERT [2]

DIDEVENT

IOpenRowset::OpenRowset

_ROW_ASYNCINSERT [2]

DIDEVENT

IRowset::AddRefRows

None

N/A

IRowset::GetData

None

N/A

IRowset::GetNextRows

_ROW_ACTIVATE

DIDEVENT

_ROWSET_FETCHPOSITIONCHANGE

All Phases

IRowset::ReleaseRows

_ROW_RELEASE

DIDEVENT

IRowset::RestartPosition

_ROWSET_FETCHPOSITIONCHANGE

All Phases

_ROWSET_CHANGED [3]

All Phases

IRowsetChange::DeleteRows

_ROW_DELETE

All Phases

IRowsetChange::InsertRow

_ROW_INSERT

All Phases

IRowsetChange::SetData

_ROW_FIRSTCHANGE [4]

All Phases

_COLUMN_SET

All Phases

_COLUMN_RECALCULATED

DIDEVENT

IRowsetIndex::Seek

_ROWSET_FETCHPOSITIONCHANGE

All Phases

IRowsetLocate::Compare

None

N/A

IRowsetLocate::GetRowsAt

_ROW_ACTIVATE

DIDEVENT

IRowsetLocate::GetRowsByBookmark

_ROW_ACTIVATE

DIDEVENT

IRowsetLocate::Hash

None

N/A

IRowsetRefresh::GetLastVisibleData

None

N/A

IRowsetRefresh::RefreshVisibleData

_ROW_RESYNCH

All Phases

IRowsetScroll::GetApproximatePosition

None

N/A

IRowsetScroll::GetRowsAtRatio

_ROW_ACTIVATE

DIDEVENT

IRowsetUpdate::GetOriginalData

None

N/A

IRowsetUpdate::GetPendingRows

None

N/A

IRowsetUpdate::Undo

_ROW_UNDOCHANGE

All Phases

_ROW_UNDOINSERT

All Phases

_ROW_UNDODELETE

All Phases

IRowsetUpdate::Update

_ROW_UPDATE

All Phases

All other rowset methods

None

N/A

[1] Methods generate only the listed DBREASON values, even though other reasons might seem appropriate. For example, IRowsetChange::InsertRow generates only DBREASON_ROW_INSERT even though DBREASON_COLUMN_SET, DBREASON_ROW_FIRSTCHANGE, and DBREASON_ROW_ACTIVATE might appear to be applicable.

[2] ICommand::Execute and IOpenRowset::OpenRowset generate this DBREASON only when the rowsets are being populated asynchronously.

[3] IRowset::RestartPosition generates this DBREASON only when the metadata for the columns has changed.

[4] DBREASON_ROW_FIRSTCHANGE is generated only the first time a column in the row is changed. For more information, see the table of DBREASON values earlier in this section.

Method

Description

OnFieldChange

Notifies the consumer of any change to the value of a column.

OnRowChange

Notifies the consumer of the first change to a row or of any change that affects the entire row.

OnRowsetChange

Notifies the consumer of any change affecting the entire rowset.

This topic is a part of: