Recupero di dati di grandi dimensioni
I consumer devono in genere isolare il codice che crea un oggetto di archiviazione del provider OLE DB di SQL Server Native Client da altro codice che gestisce i dati a cui non si fa riferimento tramite un puntatore di interfaccia ISequentialStream.
In questo argomento vengono descritte le funzionalità disponibili con le funzioni seguenti:
IRowset:GetData
IRow::GetColumns
ICommand::Execute
Se la proprietà DBPROP_ACCESSORDER (nel gruppo di proprietà del set di righe) è impostata sui valori DBPROPVAL_AO_SEQUENTIAL o DBPROPVAL_AO_SEQUENTIALSTORAGEOBJECTS, il consumer deve recuperare una singola riga di dati in una chiamata al metodo GetNextRows, in quanto i dati BLOB non vengono memorizzati nel buffer. Se il valore di DBPROP_ACCESSORDER è impostato su DBPROPVAL_AO_RANDOM, il consumer può recuperare più righe di dati in GetNextRows.
Il provider OLE DB di SQL Server Native Client non recupera dati di grandi dimensioni da SQL Server fino a quando non riceve una richiesta a tale scopo dal consumer. Il consumer deve associare tutti i dati di tipo short in una funzione di accesso e quindi utilizzare una o più funzioni di accesso temporanee per recuperare valori di dati di grandi dimensioni come richiesto.
Esempio
In questo esempio viene recuperato un valore di dati di grandi dimensioni da una singola colonna:
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);
}