次の方法で共有


大きなデータの取得

一般に、コンシューマは、SQL Server Native Client OLE DB プロバイダのストレージ オブジェクトを作成するコードと、ISequentialStream インターフェイス ポインタにより参照されないデータを処理するコードを区別する必要があります。

このトピックでは、次の関数で使用可能な機能について説明します。

  • IRowset:GetData

  • IRow::GetColumns

  • ICommand::Execute

行セット プロパティ グループの DBPROP_ACCESSORDER プロパティに DBPROPVAL_AO_SEQUENTIAL または DBPROPVAL_AO_SEQUENTIALSTORAGEOBJECTS のいずれかの値を設定した場合は、BLOB データがバッファに格納されないので、GetNextRows メソッドの呼び出しで、1 行分のデータをフェッチする必要があります。DBPROP_ACCESSORDER の値を DBPROPVAL_AO_RANDOM に設定した場合は、GetNextRows で複数行のデータをフェッチできます。

SQL Server Native Client OLE DB プロバイダは、コンシューマから要求されるまで、SQL Server から大きなデータを取得しません。コンシューマは、すべての短いデータを 1 つのアクセサにバインドし、次に 1 つ以上の一時アクセサを使用して、必要に応じて大きなデータ値を取得する必要があります。

次の例では、大きなデータ値を 1 つの列から取得します。

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);
    }