IRowsetChange::SetData

Sets data values in one or more columns in a row.

Note

IRowsetChange::SetData does not work in multi-threaded environments.

Syntax

HRESULT SetData (
   HROW        hRow,
   HACCESSOR   hAccessor,
   void       *pData);

Parameters

  • hRow
    [in] The handle of the row in which to set data.

  • hAccessor
    [in] The handle of the accessor to use. If hAccessor is the handle of a null accessor (cBindings in IAccessor::CreateAccessor was zero), IRowsetChange::SetData does not set any data values.

  • pData
    [in] A pointer to memory containing the new data values, at offsets that correspond to the bindings in the accessor.

Return Code

  • S_OK
    The method succeeded. The status of all columns bound by the accessor is set to DBSTATUS_S_OK or DBSTATUS_S_ISNULL.

  • DB_S_ERRORSOCCURRED
    An error occurred while setting data for one or more columns, but data was successfully set for at least one column. To determine the columns for which data was returned, the consumer checks the status values. For a list of status values that can be returned by this method, see "Status Values Used When Setting Data" in Status.

  • DB_S_MULTIPLECHANGES
    The rowset was in immediate update mode, and updating the row caused more than one row to be updated in the data store. For more information, see DBPROP_REPORTMULTIPLECHANGES in Rowset Property Group in Appendix C.

    This return code takes precedence over DB_S_ERRORSOCCURRED. That is, if the conditions described here and in those described in DB_S_ERRORSOCCURRED both occur, the provider returns this code. When the consumer receives this return code, it should also check for the conditions described in DB_S_ERRORSOCCURRED.

  • E_FAIL
    A provider-specific error occurred.

  • E_INVALIDARG
    pData was a null pointer, and the accessor was not a null accessor.

  • E_UNEXPECTED
    ITransaction::Commit or ITransaction::Abort was called, and the object is in a zombie state.

  • DB_E_ABORTLIMITREACHED
    The rowset was in immediate update mode, and the row was not updated due to reaching a limit on the server, such as a query execution timing out.

  • DB_E_BADACCESSORHANDLE
    hAccessor was invalid.

  • DB_E_BADACCESSORTYPE
    The specified accessor was not a row accessor or was a reference accessor. Some providers may return DB_E_BADACCESSORHANDLE instead of this error code when command accessors are passed to the rowset.

  • DB_E_BADROWHANDLE
    hRow was invalid.

  • DB_E_CANCELED
    The change was canceled during notification. No columns are changed.

  • DB_E_CANTCONVERTVALUE
    The data value for one or more columns couldn't be converted for reasons other than sign mismatch or data overflow, and the provider was unable to determine which columns couldn't be converted. Providers that can detect which columns could not be converted return DB_S_ERRORSOCCURRED and set the status flag for the columns that couldn't be converted to DBSTATUS_E_CANTCONVERTVALUE.

  • DB_E_CONCURRENCYVIOLATION
    The rowset was using optimistic concurrency and the value of a column has been changed since the containing row was last fetched or resynchronized. IRowsetChange::SetData returns this error only when the rowset is in immediate update mode.

  • DB_E_DATAOVERFLOW
    Conversion failed because the data value for one or more columns overflowed the type used by the provider and the provider was unable to determine which columns caused the overflow. Providers that can detect which columns caused the overflow return DB_S_ERRORSOCCURRED and set the status flag for the columns in violation to DBSTATUS_E_DATAOVERFLOW.

  • DB_E_DELETEDROW
    hRow referred to a row with a pending delete or for which a deletion had been transmitted to the data store.

  • DB_E_ERRORSOCCURRED
    An error occurred while setting data for one or more columns, and data was not successfully set for any columns. To determine the columns for which values were invalid, the consumer checks the status values. For a list of status values that can be returned by this method, see "Status Values Used When Setting Data" in Status.

  • DB_E_INTEGRITYVIOLATION
    The data violated the integrity constraints for one or more columns of the rowset, and the provider was unable to determine which columns violated the integrity constraints. Providers that can detect which columns violated the integrity constraints return DB_S_ERRORSOCCURRED and set the status flag for the columns in violation to DBSTATUS_E_INTEGRITYVIOLATION.

  • DB_E_MAXPENDCHANGESEXCEEDED
    The number of rows that have pending changes has exceeded the limit specified by the DBPROP_MAXPENDINGROWS property.

  • DB_E_NEWLYINSERTED
    DBPROP_CHANGEINSERTEDROWS was VARIANT_FALSE, and hRow referred to a row for which the insertion has been transmitted to the data store.

  • DB_E_NOTREENTRANT
    The consumer called this method while it was processing a notification, and it is an error to call this method while processing the specified DBREASON value.

  • DB_E_NOTSUPPORTED
    The provider does not support this method, or the corresponding bit of DBPROP_UPDATABILITY is not set.

    Note

    The spec, as of 2.1, does not require this return code if the corresponding bit is not set.

  • DB_SEC_E_PERMISSIONDENIED
    The consumer did not have sufficient permission to update the row, or the row was not in a state suitable for updating. (Typical reasons for returning this code are the row is read-only, or changes have not yet been committed on a rowset in delayed update mode.)

Comments

If this method performs deferred accessor validation and that validation takes place before any data is transferred, it can also return any of the following return codes for the applicable reasons listed in the corresponding DBBINDSTATUS values in IAccessor::CreateAccessor:

  • E_NOINTERFACE

  • DB_E_BADBINDINFO

  • DB_E_BADORDINAL

  • DB_E_BADSTORAGEFLAGS

  • DB_E_UNSUPPORTEDCONVERSION

IRowsetChange::SetData sets data values in one or more columns in a row. For a complete description of how SetData sets data, see Setting Data.

In delayed update mode, these changes are buffered locally in the rowset and are transmitted to the data store only when IRowsetUpdate::Update is called. In immediate update mode, the changes are immediately transmitted to the data store. For more information, see Changing Data.

If a computed column depends on a column that is changed with IRowsetChange::SetData, the provider is not required to compute the new value of the computed column. If the provider computes the new value, it sends a notification to the consumer. If the provider does not compute the new value but lets the data store do so, the computed value is not available until after the change is transmitted to the data store ? that is, after IRowsetChange::SetData is called in immediate update mode or after IRowsetUpdate::Update if SetData is called in delayed update mode. Whenever the provider detects that the data store has computed a new column value, it is required to send a COLUMN_RECALCULATED notification to the consumer. To retrieve the computed value in this case, the consumer calls RefreshVisibleData or GetLastVisibleData in IRowsetRefresh. Bookmark columns are often computed ? for example, when the bookmark is the primary key or is a ROWID assigned by the data store.

If IRowsetChange::SetData changes a column that is used to order the rowset, the DBPROP_IMMOBILEROWS property describes whether the row is moved based on its new value. If this property is VARIANT_TRUE, the row is not moved. If this property is VARIANT_FALSE, the row is moved. If the rowset is not ordered, the position of updated rows is not changed. If the rowset is built on a set of key columns (typically a rowset for which DBPROP_OTHERUPDATEDELETE is VARIANT_TRUE but DBPROP_OTHERINSERT is VARIANT_FALSE), changing the value of key column is generally equivalent to deleting the current row and inserting a new one. Therefore, the row may appear to move or even disappear from the rowset (if DBPROP_OWNINSERT is VARIANT_FALSE), even though the DBPROP_IMMOBILEROWS property is VARIANT_TRUE.

When the consumer passes a pointer to a storage object to IRowsetChange::SetData, SetData replaces the data in the column with the data in the new storage object. If the consumer wants only to delete the data in the column, it sets the column status to DBSTATUS_S_OK and passes a null pointer instead of a pointer to a storage object. For more information, see Getting and Setting BLOB Data with Storage Objects. If the rowset is in immediate update mode, storage object data is always transmitted immediately to the data store. If it is in delayed update mode, whether it is transmitted immediately or delayed depends on the DBPROP_DELAYSTORAGEOBJECTS property.

When setting rowset column data values from a consumer's storage object, the provider is responsible for releasing the storage object. When the provider has finished using the consumer's storage object, it calls IUnknown::Release to release the pointer. If the consumer wants to ensure access to its storage object after IRowsetChange::SetData returns, it must call IUnknown::AddRef on the pointer before calling IRowsetChange::SetData.

It is the consumer's responsibility to release VARIANTs stored in *pData. The consumer should call the COM method VariantClear when a VARIANT is no longer needed.

Although IRowsetChange::SetData can detect domain constraint and some table constraint schema violations, it is not required to do so. Such validation can be delayed until the changes are transmitted to the data store with IRowsetUpdate::Update or the transaction is committed with ITransaction::Commit. This delay is often necessary because of dependencies on values in other columns or tables.

IRowsetChange::SetData cannot be called for rows with pending or transmitted deletes.

The DBPROP_COLUMNRESTRICT and DBPROP_ROWRESTRICT properties affect how security is enforced and how security errors are returned. If DBPROP_COLUMNRESTRICT is VARIANT_TRUE, the consumer might not have write permission on at least one column. If the consumer attempts to write to these columns, IRowsetChange::SetData returns a column status of DBSTATUS_E_PERMISSIONDENIED and a return code of DB_S_ERRORSOCCURRED. If the DBPROP_ROWRESTRICT property is VARIANT_TRUE, the consumer might not have permission to update some rows. If the consumer attempts to update one of these rows, IRowsetChange::SetData returns a code of DB_SEC_E_PERMISSIONDENIED and no data is set.

If any consumer of the rowset is using notifications, the provider sends notifications. These notifications can be vetoed, in which case the provider sends the DBEVENTPHASE_FAILEDTODO phase of the notification. When the consumer then calls IRowsetUpdate::Update, if the update is in delayed mode, the provider does not send additional DBREASON_COLUMN_SET notifications for the rows. However, if IRowsetUpdate::Update computes the value of computed columns, it sends DBREASON_COLUMN_RECALCULATED notifications. In this case, the provider must either be prepared to undo all pending changes for the row, and return DBREASON_ROW_UNDOCHANGE, or set the fCantDeny flag to TRUE.

The following sequence of notifications occurs for a rowset operating in delayed update mode:

  1. If the row is being changed for the first time since it was created, or if changes were transmitted, the provider sends the DBEVENTPHASE_OKTODO and DBEVENTPHASE_ABOUTTODO phases of the DBREASON_ROW_FIRSTCHANGE notification.

  2. The provider sends the DBEVENTPHASE_OKTODO, DBEVENTPHASE_ABOUTTODO, and DBEVENTPHASE_SYNCHAFTER phases of the DBREASON_COLUMN_SET notification, in that order, provided none of the listeners veto any of the phases. The notification covers all the columns defined by the accessor used in the call to IRowsetChange::SetData.

  3. The provider sends the DBEVENTPHASE_SYNCHAFTER phase of the DBREASON_ROW_FIRSTCHANGE notification, assuming the provider sent the earlier phases of this notification.

  4. The provider sends the DBEVENTPHASE_DIDEVENT phase of the DBREASON_COLUMN_SET notification.

  5. The provider sends the DBEVENTPHASE_DIDEVENT phase of the ROW_FIRSTCHANGE notification.

See Also

Reference

IRowset::GetData

IRowsetChange::InsertRow

IRowsetUpdate::Undo

IRowsetUpdate::Update