Freigeben über


Abrufen großer Datenmengen

Im Allgemeinen sollten Consumer Code, der ein Speicherobjekt des SQL Server Native Client OLE DB-Anbieters erzeugt, von anderem Code isolieren, der Daten verarbeitet, die nicht durch einen ISequentialStream-Schnittstellenzeiger referenziert sind.

In diesem Thema wird die mit folgenden Funktionen verfügbare Funktionalität behandelt:

  • IRowset:GetData

  • IRow::GetColumns

  • ICommand::Execute

Wenn die Eigenschaft DBPROP_ACCESSORDER (in der Rowset-Eigenschaftengruppe) auf die Werte DBPROPVAL_AO_SEQUENTIAL oder DBPROPVAL_AO_SEQUENTIALSTORAGEOBJECTS eingestellt ist, sollte der Consumer in einem Aufruf der GetNextRows-Methode nur eine einzige Datenzeile abrufen, da BLOB-Daten nicht zwischengespeichert werden. Ist der Wert von DBPROP_ACCESSORDER auf DBPROPVAL_AO_RANDOM eingestellt, kann der Consumer mehrere Datenzeilen mit GetNextRows abrufen.

Der SQL Server Native Client OLE DB-Anbieter ruft erst dann große Datenmengen von SQL Server ab, wenn er vom Consumer dazu aufgefordert wird. Der Consumer sollte alle kleinen Datenmengen in einem Accessor zusammenfassen und dann einen oder mehrere Accessoren zum Abrufen großer Datenwerte verwenden.

Beispiel

In diesem Beispiel wird ein großer Datenwert aus einer einzelnen Spalte abgerufen:

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.
        pIAccessor->Release();
        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));

            do
                {
                if (SUCCEEDED(hr =
                    pISequentialStream->Read(pUnboundData,
                    BLOCK_SIZE, &cbRead)))
                    {
                    pUnboundData += cbRead;
                    }
                }
            while (SUCCEEDED(hr) && cbRead >= BLOCK_SIZE);

            pISequentialStream->Release();
            }
        }
    else
        {
        // Process error from GetData.
        }

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

    return (hr);
    }