Récupérer des lignes à l'aide de signets (OLE DB)
Le consommateur attribue au champ dwFlag
de la structure de liaison la valeur DBCOLUMNSINFO_ISBOOKMARK pour indiquer que la colonne est utilisée comme signet. Le consommateur définit également la propriété d'ensemble de lignes DBPROP_BOOKMARKS avec la valeur VARIANT_TRUE. Cela permet à la colonne 0 d'être présente dans l'ensemble de lignes. IRowsetLocate::GetRowsAt
est ensuite utilisé pour extraire les lignes, en commençant par la ligne spécifiée par un offset à partir d'un signet.
Important
Lorsque c'est possible, utilisez l'authentification Windows. Si l'authentification Windows n'est pas disponible, invitez les utilisateurs à entrer leurs informations d'identification au moment de l'exécution. Évitez de stocker ces informations dans un fichier. Si vous devez rendre les informations d'identification persistantes, chiffrez-les avec l' API de chiffrement Win32.
Pour extraire des lignes à l'aide de signets
Établissez une connexion à la source de données.
Définissez la propriété DBPROP_IRowsetLocate de l'ensemble de lignes avec la valeur VARIANT_TRUE.
Exécutez la commande.
Définissez le champ
dwFlag
de la structure de liaison avec l'indicateur DBCOLUMNSINFO_ISBOOKMARK de la colonne qui sera utilisée comme signet.Utilisez
IRowsetLocate::GetRowsAt
pour extraire les lignes, en commençant par la ligne spécifiée par un offset du signet.
Exemple
Cet exemple montre comment extraire des lignes au moyen d'un signet. Cet exemple n'est pas pris en charge sur la plateforme IA64.
Dans cet exemple, la cinquième ligne est récupérée du jeu de résultats produit par l'exécution d'une instruction SELECT.
Cet exemple requiert l'exemple de base de données AdventureWorks, que vous pouvez télécharger à partir de la page d'accueil des exemples et projets de communautés Microsoft SQL Server .
Compilez avec ole32.lib oleaut32.lib et exécutez le code C++ suivant. Cette application vous permet de vous connecter à l'instance de SQL Server par défaut de votre ordinateur. Sur certains systèmes d'exploitation Windows, vous devrez remplacer (localhost) ou (local) par le nom de votre instance SQL Server . Pour vous connecter à une instance nommée, remplacez la chaîne de connexion L"(local)" par L"(local)\\name", où name correspond à l'instance nommée. Par défaut, SQL Server Express est installé dans une instance nommée. Assurez-vous que votre variable d'environnement INCLUDE inclut le répertoire qui contient sqlncli.h.
// compile with: ole32.lib oleaut32.lib
int InitializeAndEstablishConnection();
int ProcessResultSet();
#define UNICODE
#define _UNICODE
#define DBINITCONSTANTS
#define INITGUID
#define OLEDBVER 0x0250 // to include correct interfaces
#include <stdio.h>
#include <tchar.h>
#include <stddef.h>
#include <windows.h>
#include <iostream>
#include <oledb.h>
#include <sqlncli.h>
using namespace std;
IDBInitialize* pIDBInitialize = NULL;
IDBProperties* pIDBProperties = NULL;
IDBCreateSession* pIDBCreateSession = NULL;
IDBCreateCommand* pIDBCreateCommand = NULL;
ICommandProperties* pICommandProperties = NULL;
ICommandText* pICommandText = NULL;
IRowset* pIRowset = NULL;
IColumnsInfo* pIColumnsInfo = NULL;
DBCOLUMNINFO* pDBColumnInfo = NULL;
IAccessor* pIAccessor = NULL;
IRowsetLocate* pIRowsetLocate = NULL;
DBPROP InitProperties[4];
DBPROPSET rgInitPropSet[1];
DBPROPSET rgPropSets[1];
DBPROP rgProperties[1];
ULONG i, j;
HRESULT hresult;
DBROWCOUNT cNumRows = 0;
DBORDINAL lNumCols;
WCHAR* pStringsBuffer;
DBBINDING* pBindings;
DBLENGTH ConsumerBufferColOffset = 0;
HACCESSOR hAccessor;
DBCOUNTITEM lNumRowsRetrieved;
HROW hRows[5];
HROW* pRows = &hRows[0];
char* pBuffer;
int main() {
// The command to execute.
// WCHAR* wCmdString = OLESTR(" SELECT title_id, title FROM titles ");
WCHAR* wCmdString = OLESTR(" SELECT Name FROM Production.Product");
// Initialize and establish a connection to the data source.
if (InitializeAndEstablishConnection() == -1) {
// Handle error.
cout << "Failed to initialize and connect to the server.\n";
return -1;
}
// Create a session object.
if (FAILED(pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void**) &pIDBCreateSession))) {
cout << "Failed to obtain IDBCreateSession interface.\n";
// Handle error.
return -1;
}
if (FAILED(pIDBCreateSession->CreateSession(NULL, IID_IDBCreateCommand, (IUnknown**) &pIDBCreateCommand))) {
cout << "pIDBCreateSession->CreateSession failed.\n";
// Handle error.
return -1;
}
// Access the ICommandText interface.
if (FAILED(pIDBCreateCommand->CreateCommand( NULL, IID_ICommandText, (IUnknown**) &pICommandText))) {
cout << "Failed to access ICommand interface.\n";
// Handle error.
return -1;
}
// Set DBPROP_IRowsetLocate
if (FAILED(pICommandText->QueryInterface( IID_ICommandProperties, (void **) &pICommandProperties ))) {
cout << "Failed to obtain ICommandProperties interface.\n";
// Handle error.
return -1;
}
// Set DBPROP_IRowsetLocate to VARIANT_TRUE to get the IRowsetLocate interface.
VariantInit(&rgProperties[0].vValue);
rgPropSets[0].guidPropertySet = DBPROPSET_ROWSET;
rgPropSets[0].cProperties = 1;
rgPropSets[0].rgProperties = rgProperties;
// Set properties in the property group (DBPROPSET_ROWSET)
rgPropSets[0].rgProperties[0].dwPropertyID = DBPROP_IRowsetLocate;
rgPropSets[0].rgProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;
rgPropSets[0].rgProperties[0].colid = DB_NULLID;
rgPropSets[0].rgProperties[0].vValue.vt = VT_BOOL;
rgPropSets[0].rgProperties[0].vValue.boolVal= VARIANT_TRUE;
// Set the rowset properties.
hresult = pICommandText->QueryInterface( IID_ICommandProperties,(void **)&pICommandProperties);
if (FAILED(hresult)) {
printf("Failed to get ICommandProperties to set rowset properties.\n");
// Release any references and return.
return -1;
}
hresult = pICommandProperties->SetProperties(1, rgPropSets);
if (FAILED(hresult)) {
printf("Execute failed to set rowset properties.\n");
// Release any references and return.
return -1;
}
pICommandProperties->Release();
// Specify the command text.
if (FAILED(pICommandText->SetCommandText(DBGUID_DBSQL, wCmdString))) {
cout << "Failed to set command text.\n";
// Handle error.
return -1;
}
// Execute the command.
if (FAILED(hresult =
pICommandText->Execute( NULL, IID_IRowset, NULL, &cNumRows, (IUnknown **) &pIRowset))) {
cout << "Failed to execute command.\n";
// Handle error.
return -1;
}
ProcessResultSet();
pIRowset->Release();
// Free up memory.
pICommandText->Release();
pIDBCreateCommand->Release();
pIDBCreateSession->Release();
pIDBInitialize->Uninitialize();
pIDBInitialize->Release();
// Release COM library.
CoUninitialize();
return -1;
}
int InitializeAndEstablishConnection() {
// Initialize the COM library.
CoInitialize(NULL);
// Obtain access to the SQL Server Native Client OLe DB provider.
CoCreateInstance( CLSID_SQLNCLI11, NULL, CLSCTX_INPROC_SERVER, IID_IDBInitialize, (void **) &pIDBInitialize);
// Initialize the property values that are the same for each property.
for ( i = 0 ; i < 4 ; i++ ) {
VariantInit(&InitProperties[i].vValue);
InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
InitProperties[i].colid = DB_NULLID;
}
// Server name.
InitProperties[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
InitProperties[0].vValue.vt = VT_BSTR;
InitProperties[0].vValue.bstrVal = SysAllocString(L"(local)");
// Database.
InitProperties[1].dwPropertyID = DBPROP_INIT_CATALOG;
InitProperties[1].vValue.vt = VT_BSTR;
InitProperties[1].vValue.bstrVal = SysAllocString(L"AdventureWorks");
InitProperties[2].dwPropertyID = DBPROP_AUTH_INTEGRATED;
InitProperties[2].vValue.vt = VT_BSTR;
InitProperties[2].vValue.bstrVal = SysAllocString(L"SSPI");
// Construct the PropertySet array.
rgInitPropSet[0].guidPropertySet = DBPROPSET_DBINIT;
rgInitPropSet[0].cProperties = 4;
rgInitPropSet[0].rgProperties = InitProperties;
// Set initialization properties.
pIDBInitialize->QueryInterface(IID_IDBProperties, (void **)&pIDBProperties);
hresult = pIDBProperties->SetProperties(1, rgInitPropSet);
if (FAILED(hresult)) {
cout << "Failed to set initialization properties.\n";
// Handle error.
return -1;
}
pIDBProperties->Release();
// Call the initialization method to establish the connection.
if (FAILED(pIDBInitialize->Initialize())) {
cout << "Problem initializing and connecting to the data source.\n";
// Handle error.
return -1;
}
return 0;
}
#ifdef _WIN64
#define BUFFER_ALIGNMENT 8
#else
#define BUFFER_ALIGNMENT 4
#endif
#define ROUND_UP(value) (value + (BUFFER_ALIGNMENT - 1) & ~(BUFFER_ALIGNMENT - 1))
int ProcessResultSet() {
HRESULT hr;
// Retrieve 5th row from the rowset (for example).
DBBKMARK iBookmark = 5;
pIRowset->QueryInterface(IID_IColumnsInfo, (void **)&pIColumnsInfo);
pIColumnsInfo->GetColumnInfo( &lNumCols, &pDBColumnInfo, &pStringsBuffer );
// Create a DBBINDING array.
pBindings = new DBBINDING[lNumCols];
if (!(pBindings /* = new DBBINDING[lNumCols] */ )) {
// Handle error.
return -1;
}
// Using the ColumnInfo strucuture, fill out the pBindings array.
for ( j = 0 ; j < lNumCols ; j++ ) {
pBindings[j].iOrdinal = j;
pBindings[j].obValue = ConsumerBufferColOffset;
pBindings[j].pTypeInfo = NULL;
pBindings[j].pObject = NULL;
pBindings[j].pBindExt = NULL;
pBindings[j].dwPart = DBPART_VALUE;
pBindings[j].dwMemOwner = DBMEMOWNER_CLIENTOWNED;
pBindings[j].eParamIO = DBPARAMIO_NOTPARAM;
pBindings[j].cbMaxLen = pDBColumnInfo[j].ulColumnSize + 1; // + 1 for null terminator
pBindings[j].dwFlags = 0;
pBindings[j].wType = pDBColumnInfo[j].wType;
pBindings[j].bPrecision = pDBColumnInfo[j].bPrecision;
pBindings[j].bScale = pDBColumnInfo[j].bScale;
// Recalculate the next buffer offset.
ConsumerBufferColOffset = ConsumerBufferColOffset + pDBColumnInfo[j].ulColumnSize;
ConsumerBufferColOffset = ROUND_UP(ConsumerBufferColOffset);
};
// Indicate that the first field is used as a bookmark by setting
// dwFlags to DBCOLUMNFLAGS_ISBOOKMARK.
pBindings[0].dwFlags = DBCOLUMNFLAGS_ISBOOKMARK;
// Get IAccessor interface.
hr = pIRowset->QueryInterface( IID_IAccessor, (void **)&pIAccessor);
if (FAILED(hr)) {
printf("Failed to get IAccessor interface.\n");
// Handle error.
return -1;
}
// Create accessor.
hr = pIAccessor->CreateAccessor( DBACCESSOR_ROWDATA,
lNumCols,
pBindings,
0,
&hAccessor,
NULL);
if (FAILED(hr)) {
printf("Failed to create an accessor.\n");
// Handle error.
return -1;
}
hr = pIRowset->QueryInterface( IID_IRowsetLocate, (void **) &pIRowsetLocate);
if (FAILED(hr)) {
printf("Failed to get IRowsetLocate interface.\n");
// Handle error.
return -1;
}
hr = pIRowsetLocate->GetRowsAt( 0,
NULL,
sizeof(DBBKMARK),
(BYTE *) &iBookmark,
0,
1,
&lNumRowsRetrieved,
&pRows);
if (FAILED(hr)) {
printf("Calling the GetRowsAt method failed.\n");
// Handle error.
return -1;
}
// Create buffer and retrieve data.
pBuffer = new char[ConsumerBufferColOffset];
if (!(pBuffer /* = new char[ConsumerBufferColOffset] */ )) {
// Handle error.
return -1;
}
memset(pBuffer, 0, ConsumerBufferColOffset);
hr = pIRowset->GetData(hRows[0], hAccessor, pBuffer);
if (FAILED(hr)) {
printf("Failed GetDataCall.\n");
// Handle error.
return -1;
}
char szTitle[7] = {0};
strncpy_s(szTitle, &pBuffer[pBindings[1].obValue], 6);
printf("%S\n", &pBuffer[pBindings[1].obValue]);
pIRowset->ReleaseRows(lNumRowsRetrieved, hRows, NULL, NULL, NULL);
// Release allocated memory.
delete [] pBuffer;
pIAccessor->ReleaseAccessor(hAccessor, NULL);
pIAccessor->Release();
delete [] pBindings;
return 0;
}