Bagikan melalui


IRowset::GetData

Retrieves data from the rowset's copy of the row.

Syntax

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

Parameters

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

    Warning

    The consumer must ensure that hRow contains a valid row handle; the provider might not validate hRow before using it. The result of passing the handle of a deleted row is provider-specific, although the provider cannot terminate abnormally. For example, the provider might return DB_E_BADROWHANDLE, DB_E_DELETEDROW, or it might get data from a different row. The result of passing an invalid row handle in hRow is undefined.

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

    Warning

    The consumer must ensure that hAccessor contains a valid accessor handle; the provider might not validate hAccessor before using it. The result of passing an invalid accessor handle in hAccessor is undefined.

  • pData
    [out] A pointer to a buffer in which to return the data. The consumer allocates memory for this buffer. This pointer must be a valid pointer to a contiguous block of consumer-owned memory into which the data will be written.

Return Code

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

  • DB_S_ERRORSOCCURRED
    An error occurred while returning data for one or more columns, but data was successfully returned 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 Getting Data" in Status.

  • 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_BADACCESSORHANDLE
    hAccessor was invalid. Providers are not required to check for this condition, because doing so might slow the method significantly.

  • DB_E_BADACCESSORTYPE
    The specified accessor was not a row 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. Providers are not required to check for this condition, because doing so might slow the method significantly.

  • DB_E_DELETEDROW
    hRow referred to a pending delete row or a row for which a deletion had been transmitted to the data store. Providers are not required to check for this condition, because doing so might slow the method significantly.

  • DB_E_ERRORSOCCURRED
    Errors occurred while returning data for all columns. To determine what errors occurred, the consumer checks the status values. For a list of status values that can be returned by this method, see "Status Values Used When Getting Data" in Status.

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 reasons listed in the corresponding DBBINDSTATUS values in IAccessor::CreateAccessor:

  • E_NOINTERFACE

  • DB_E_BADBINDINFO

  • DB_E_BADORDINAL

  • DB_E_BADSTORAGEFLAGS

  • DB_E_UNSUPPORTEDCONVERSION

This method makes no logical change to the state of the object.

A consumer calls IRowset::GetData to retrieve data from rows that have been fetched by prior calls to methods such as IRowset::GetNextRows. For a complete description of how IRowset::GetData retrieves data, see Getting Data.

A consumer can call IRowset::GetData any number of times. In each call, it can pass a different accessor and the address of a different buffer. This means that the consumer can get as many copies of the data as it wants, and it can get data in different types if alternate conversions are available.

IRowset::GetData does not enforce any security restrictions. The provider must not create a rowset that includes columns for which the consumer does not have read privileges, so IRowset::GetData never encounters problems accessing the data for a column. The rowset can contain columns to which the consumer does not have write permission if DBPROP_COLUMNRESTRICT is VARIANT_TRUE. The methods that fetch rows must not return the handles of rows for which the consumer does not have read privileges, so IRowset::GetData never encounters problems accessing a row. Such rows might exist if the DBPROP_ROWRESTRICT property is VARIANT_TRUE.

If IRowset::GetData fails, the memory to which pData points is not freed but its contents are undefined. If before GetData failed the provider allocated any memory for return to the consumer, the provider frees this memory and does not return it to the consumer. The same is true if DB_E_ERRORSOCCURRED was returned but the consumer did not request status values in the binding.

IRowset::GetData must be reentrant during notifications. If the provider calls a method from IRowsetNotify in the consumer, the consumer must be able to call IRowset::GetData while processing the notification method.

The following example shows how a reference accessor is used.

#include <oledb.h>
#include <stddef.h>
IRowset *     TheRowset;
IAccessor *   TheRowsetAccessor;
HROW          hRow;

int main() {
   struct ExactlyTheSame {
      long l;
      double d;
      short  i;
   };
   HACCESSOR hRawAccess;
   static DBBINDING ExactBindings [3] = {
      {
         1,                          // iOrdinal
         offsetof (ExactlyTheSame,l), // obValue
         0,                          // No length binding
         0,                          // No Status binding
         NULL,                       // No TypeInfo
         NULL,                       // No Object
         NULL,                       // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,   // Ignored
         DBPARAMIO_NOTPARAM,
         sizeof (long),
         0,
         DBTYPE_I4,
         0,                          // No Precision
         0                           // No Scale
      },
      {
         2,                          // iOrdinal
         offsetof (ExactlyTheSame, d),   // obValue
         0,                          // No length binding
         0,                          // No Status binding
         NULL,                       // No TypeInfo
         NULL,                       // No Object
         NULL,                       // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,    // Ignored
         DBPARAMIO_NOTPARAM,
         sizeof (double),
         0,
         DBTYPE_R8,
         0,                          // No Precision
         0                           // No Scale
      },
      {
         3,                          // iOrdinal
         offsetof (ExactlyTheSame,i), // obValue
         0,                          // No length binding
         0,                          // No Status binding
         NULL,                       // No TypeInfo
         NULL,                       // No Object
         NULL,                       // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,    // Ignored
         DBPARAMIO_NOTPARAM,
         sizeof (short),
         0,
         DBTYPE_I2,
         0,                          // No Precision
         0                           // No Scale
      }
   };
   TheRowsetAccessor->CreateAccessor
      (DBACCESSOR_PASSBYREF, 3, ExactBindings, 0,
      &hRawAccess, NULL);

   // ...

   return 0;
}

   TheRowsetAccessor->CreateAccessor
      (DBACCESSOR_PASSBYREF, 3, ExactBindings, 0,
       &hRawAccess, NULL);

To read the column i of some row, the consumer should do the following:

short              value;
ExactlyTheSame *   pRow;
TheRowset->GetData(hRow, hRawAccess, &pRow);
value = pRow->i;

The following example shows how provider-owned memory is used:

#include <oledb.h>
#include <stddef.h>

IRowset *     TheRowset;
IAccessor *   TheRowsetAccessor;
HROW          hRow;

int main() {
   struct IndirectlySimilar {
      long *     pl;
      double *   pd;
      short *    pi;
   };
   HACCESSOR hFastAccess;
   static DBBINDING IndirectBindings [3] = {
      {
         1,                        // iOrdinal
         offsetof (IndirectlySimilar, pl),   // obValue
         0,                        // No length binding
         0,                        // No Status binding
         NULL,                     // No TypeInfo
         NULL,                     // No Object
         NULL,                     // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,
         DBPARAMIO_NOTPARAM,
         sizeof (long*),
         0,
         DBTYPE_BYREF|DBTYPE_I4,
         0,                       // No Precision
         0                        // No Scale
      },
      {
         2,                        // iOrdinal
         offsetof (IndirectlySimilar, pd),   // obValue
         0,                        // No length binding
         0,                        // No Status binding
         NULL,                     // No TypeInfo
         NULL,                     // No Object
         NULL,                     // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,
         DBPARAMIO_NOTPARAM,
         sizeof (double*),
         0,
         DBTYPE_BYREF|DBTYPE_R8,
         0,                        // No Precision
         0                         // No Scale
      },
      {
         3,                        // iOrdinal
         offsetof (IndirectlySimilar,pi),   // obValue
         0,                        // No length binding
         0,                        // No Status binding
         NULL,                     // No TypeInfo
         NULL,                     // No Object
         NULL,                     // No Extensions
         DBPART_VALUE,
         DBMEMOWNER_PROVIDEROWNED,
         DBPARAMIO_NOTPARAM,
         sizeof(short*),
         0,
         DBTYPE_BYREF|DBTYPE_I2,
         0,                        // No Precision
         0                         // No Scale
      }
   };
   TheRowsetAccessor->CreateAccessor
      (DBACCESSOR_ROWDATA, 3, IndirectBindings, 0,
       &hFastAccess, NULL );

   // ...

   return 0;
}

To read the column i of some row, the consumer should do the following:

short               value;
IndirectlySimilar   rowPs;
TheRowset->GetData (hRow, hFastAccess, &rowPs);
if (rowPs.pi)                  // Avoid null pointers
   value = *(rowPs.pi);

See Also

Reference

IRowset::GetNextRows

IRowsetChange::SetData