Was this page helpful?
Your feedback about this content is important. Let us know what you think.
Additional feedback?
1500 characters remaining
Export (0) Print
Expand All

Getting Large Data


Applies To: SQL Server 2016 Preview

In general, consumers should isolate code that creates a SQL Server Native Client OLE DB provider storage object from other code that handles data not referenced through an ISequentialStream interface pointer.

This topic refers to functionality available with the following functions:

  • IRowset:GetData

  • IRow::GetColumns

  • ICommand::Execute

If the DBPROP_ACCESSORDER property (in the rowset property group) is set to either of the values DBPROPVAL_AO_SEQUENTIAL or DBPROPVAL_AO_SEQUENTIALSTORAGEOBJECTS, the consumer should fetch only a single row of data in a call to the GetNextRows method because BLOB data is not buffered. If the value of DBPROP_ACCESSORDER is set to DBPROPVAL_AO_RANDOM, the consumer can fetch multiple rows of data in GetNextRows.

The SQL Server Native Client OLE DB provider does not retrieve large data from SQL Server until requested to do so by the consumer. The consumer should bind all short data in one accessor, and then use one or more temporary accessors to retrieve large data values as required.

This example retrieves a large data value from a single column:

HRESULT GetUnboundData
    IRowset* pIRowset,
    HROW hRow,
    ULONG nCol, 
    BYTE* pUnboundData
    UINT                cbRow = sizeof(IUnknown*) + sizeof(ULONG);
    BYTE*               pRow = new BYTE[cbRow];

    DBOBJECT            dbobject;

    IAccessor*          pIAccessor = NULL;
    HACCESSOR           haccessor;

    DBBINDING           dbbinding;
    ULONG               ulbindstatus;

    ULONG               dwStatus;
    ISequentialStream*  pISequentialStream;
    ULONG               cbRead;

    HRESULT             hr;

    // Set up the DBOBJECT structure.
    dbobject.dwFlags = STGM_READ;
    dbobject.iid = IID_ISequentialStream;

    // Create the DBBINDING, requesting a storage-object pointer from
    // The SQL Server Native Client OLE DB provider.
    dbbinding.iOrdinal = nCol;
    dbbinding.obValue = 0;
    dbbinding.obStatus = sizeof(IUnknown*);
    dbbinding.obLength = 0;
    dbbinding.pTypeInfo = NULL;
    dbbinding.pObject = &dbobject;
    dbbinding.pBindExt = NULL;
    dbbinding.dwPart = DBPART_VALUE | DBPART_STATUS;
    dbbinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
    dbbinding.eParamIO = DBPARAMIO_NOTPARAM;
    dbbinding.cbMaxLen = 0;
    dbbinding.dwFlags = 0;
    dbbinding.wType = DBTYPE_IUNKNOWN;
    dbbinding.bPrecision = 0;
    dbbinding.bScale = 0;

    if (FAILED(hr = pIRowset->
        QueryInterface(IID_IAccessor, (void**) &pIAccessor)))
        // Process QueryInterface failure.
        return (hr);

    // Create the accessor.
    if (FAILED(hr = pIAccessor->CreateAccessor(DBACCESSOR_ROWDATA, 1,
        &dbbinding, 0, &haccessor, &ulbindstatus)))
        // Process error from CreateAccessor.
        return (hr);

    // Read and process BLOCK_SIZE bytes at a time.
    if (SUCCEEDED(hr = pIRowset->GetData(hRow, haccessor, pRow)))
        dwStatus = *((ULONG*) (pRow + dbbinding.obStatus));

        if (dwStatus == DBSTATUS_S_ISNULL)
            // Process NULL data
        else if (dwStatus == DBSTATUS_S_OK)
            pISequentialStream = *((ISequentialStream**) 
                (pRow + dbbinding.obValue));

                if (SUCCEEDED(hr =
                    BLOCK_SIZE, &cbRead)))
                    pUnboundData += cbRead;
            while (SUCCEEDED(hr) && cbRead >= BLOCK_SIZE);

        // Process error from GetData.

    pIAccessor->ReleaseAccessor(haccessor, NULL);
    delete [] pRow;

    return (hr);

Community Additions

© 2015 Microsoft