Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
In questo avvio rapido, costruisci un'applicazione console Windows C++ con Visual Studio 2022 e versioni successive. L'applicazione si collega a database SQL di Azure, SQL database in Microsoft Fabric o SQL Server con Microsoft OLE DB Driver 19 for SQL Server. Esegue una query parametrizzata sui AdventureWorksLT dati campione e verifica il risultato.
Prerequisiti
- Visual Studio 2022 e versioni successive con il carico di lavoro Sviluppo desktop con C++. Questo componente installa il Prompt dei comandi di Native Tools x64 usato in questa guida introduttiva rapida. Per le istruzioni per aprirlo, vedi Usa una scorciatoia del prompt di comando per sviluppatori ospitati a 64 bit.
- Microsoft OLE DB Driver 19 for SQL Server. Installa il driver x64 e seleziona sia i componenti client che il kit di sviluppo software (SDK).
Creare un database SQL
Crea o collegati a un database SQL su una delle seguenti piattaforme:
Per questo avvio rapido, seleziona o carica i AdventureWorksLT dati di campione.
Per un container SQL Server, crea il container e carica i dati di esempio in un comando:
sqlcmd create mssql --accept-eula --using https://aka.ms/AdventureWorksLT.bak
Per un'istanza SQL Server esistente, ripristina un AdventureWorksLT backup da database di esempio di AdventureWorks.
L'applicazione client OLE DB di questa guida introduttiva rapida viene eseguita in Windows. Un container SQL Server può funzionare su un altro host supportato.
Verificare il driver
Apri un prompt dei comandi Native Tools x64 per la tua versione Visual Studio, e poi esegui il seguente comando:
Importante
I comandi di questa guida introduttiva rapida usano la sintassi del Prompt dei comandi. Eseguili in un prompt di comandi Native Tools x64, dove il prompt termina con >. Non eseguirli in PowerShell, dove il prompt inizia con PS.
reg query HKCR\MSOLEDBSQL19
Il comando mostra il fornitore registrato MSOLEDBSQL19 .
Configura la connessione
Impostare OLEDB_CONNECTION_STRING nel prompt dei comandi degli strumenti nativi x64. L'applicazione legge la stringa di connessione dall'ambiente e non la visualizza.
Per database SQL di Azure o database SQL in Fabric, usa l'autenticazione interattiva Microsoft Entra. Sostituisci i segnaposto con il server, il database e l'ID utente Microsoft Entra dalla tua risorsa SQL:
set "OLEDB_CONNECTION_STRING=Provider=MSOLEDBSQL19;Data Source=tcp:<server>,1433;Initial Catalog=<database>;Authentication=ActiveDirectoryInteractive;User ID=<user_id>;Use Encryption for Data=Mandatory;Trust Server Certificate=false;"
Per il database SQL in Fabric, la tua identità richiede il permesso di lettura per l'elemento del database. L'autenticazione SQL non è supportata. Per altre informazioni, vedere Autenticazione nel database SQL in Microsoft Fabric.
Per un'istanza SQL Server esistente che accetta l'autenticazione Windows, usaIntegrated Security=SSPI:
set "OLEDB_CONNECTION_STRING=Provider=MSOLEDBSQL19;Data Source=tcp:<server>,1433;Initial Catalog=<database>;Integrated Security=SSPI;Use Encryption for Data=Mandatory;Trust Server Certificate=false;"
Per un'istanza o un container SQL Server che accetta l'autenticazione SQL, si utilizzaAuthentication=SqlPassword:
set "OLEDB_USER_ID=<user_id>"
set "OLEDB_PASSWORD=<password>"
set "OLEDB_CONNECTION_STRING=Provider=MSOLEDBSQL19;Data Source=tcp:<server>,1433;Initial Catalog=<database>;Authentication=SqlPassword;User ID=%OLEDB_USER_ID%;Password=%OLEDB_PASSWORD%;Use Encryption for Data=Mandatory;Trust Server Certificate=false;"
Il certificato SQL Server deve corrispondere al nome e alla catena del server con un'autorità di certificazione (CA) di cui il client Windows si fida. Per un container SQL Server, configura la Transport Layer Security (TLS) nel container e registra la CA emittente sul client Windows prima di eseguire l'applicazione. Per maggiori informazioni, vedi Crittografa le connessioni a SQL Server in Linux e Configura Motore di database di SQL Server per la cifratura delle connessioni.
Creare l'applicazione
Crea una directory di progetto:
mkdir oledb-quickstart cd oledb-quickstartCreare un file denominato
oledb-quickstart.cppcon il codice seguente:#include <windows.h> #include <oledb.h> #include <msdasc.h> #include <msoledbsql.h> #include <cstddef> #include <iomanip> #include <iostream> #include <string> template <typename T> void Release(T*& pointer) { if (pointer != nullptr) { pointer->Release(); pointer = nullptr; } } struct ParameterData { DBSTATUS status; DBLENGTH length; LONG value; }; constexpr std::size_t productNameCharacters = 51; struct RowData { DBSTATUS productIdStatus; DBLENGTH productIdLength; LONG productId; DBSTATUS nameStatus; DBLENGTH nameLength; wchar_t name[productNameCharacters]; }; std::wstring ReadEnvironmentVariable(const wchar_t* name) { const DWORD length = GetEnvironmentVariableW(name, nullptr, 0); if (length == 0) return {}; std::wstring value(length, L'\0'); const DWORD copied = GetEnvironmentVariableW( name, value.data(), length); if (copied == 0 || copied >= length) return {}; value.resize(copied); return value; } int wmain() { const std::wstring connectionString = ReadEnvironmentVariable(L"OLEDB_CONNECTION_STRING"); if (connectionString.empty()) { std::wcerr << L"Set OLEDB_CONNECTION_STRING before running.\n"; return 1; } HRESULT result = CoInitializeEx(nullptr, COINIT_MULTITHREADED); if (FAILED(result)) { std::wcerr << L"COM initialization failed: 0x" << std::hex << result << L'\n'; return 1; } IDataInitialize* dataInitialize = nullptr; IDBInitialize* dbInitialize = nullptr; IDBCreateSession* createSession = nullptr; IDBCreateCommand* createCommand = nullptr; ICommandText* commandText = nullptr; ICommandWithParameters* commandParameters = nullptr; IAccessor* parameterAccessor = nullptr; IRowset* rowset = nullptr; IAccessor* rowAccessor = nullptr; HACCESSOR parameterHandle = DB_NULL_HACCESSOR; HACCESSOR rowHandle = DB_NULL_HACCESSOR; HROW* rows = nullptr; DBCOUNTITEM rowCount = 0; bool initialized = false; do { result = CoCreateInstance( CLSID_MSDAINITIALIZE, nullptr, CLSCTX_INPROC_SERVER, IID_IDataInitialize, reinterpret_cast<void**>(&dataInitialize)); if (FAILED(result)) break; result = dataInitialize->GetDataSource( nullptr, CLSCTX_INPROC_SERVER, connectionString.c_str(), IID_IDBInitialize, reinterpret_cast<IUnknown**>(&dbInitialize)); if (FAILED(result)) break; result = dbInitialize->Initialize(); if (FAILED(result)) break; initialized = true; result = dbInitialize->QueryInterface( IID_IDBCreateSession, reinterpret_cast<void**>(&createSession)); if (FAILED(result)) break; result = createSession->CreateSession( nullptr, IID_IDBCreateCommand, reinterpret_cast<IUnknown**>(&createCommand)); if (FAILED(result)) break; result = createCommand->CreateCommand( nullptr, IID_ICommandText, reinterpret_cast<IUnknown**>(&commandText)); if (FAILED(result)) break; result = commandText->SetCommandText( DBGUID_DBSQL, const_cast<wchar_t*>( L"SELECT TOP (5) ProductID, Name " L"FROM SalesLT.Product " L"WHERE ProductID > ? " L"ORDER BY ProductID;")); if (FAILED(result)) break; result = commandText->QueryInterface( IID_ICommandWithParameters, reinterpret_cast<void**>(&commandParameters)); if (FAILED(result)) break; DB_UPARAMS parameterOrdinal = 1; wchar_t parameterType[] = L"int"; DBPARAMBINDINFO parameterInfo = {}; parameterInfo.pwszDataSourceType = parameterType; parameterInfo.ulParamSize = sizeof(LONG); parameterInfo.dwFlags = DBPARAMFLAGS_ISINPUT; parameterInfo.bPrecision = 10; result = commandParameters->SetParameterInfo( 1, ¶meterOrdinal, ¶meterInfo); if (FAILED(result)) break; result = commandText->QueryInterface( IID_IAccessor, reinterpret_cast<void**>(¶meterAccessor)); if (FAILED(result)) break; DBBINDING parameterBinding = {}; parameterBinding.iOrdinal = 1; parameterBinding.obStatus = offsetof(ParameterData, status); parameterBinding.obLength = offsetof(ParameterData, length); parameterBinding.obValue = offsetof(ParameterData, value); parameterBinding.dwPart = DBPART_STATUS | DBPART_LENGTH | DBPART_VALUE; parameterBinding.dwMemOwner = DBMEMOWNER_CLIENTOWNED; parameterBinding.eParamIO = DBPARAMIO_INPUT; parameterBinding.cbMaxLen = sizeof(LONG); parameterBinding.wType = DBTYPE_I4; parameterBinding.bPrecision = 10; DBBINDSTATUS parameterBindStatus = DBBINDSTATUS_OK; result = parameterAccessor->CreateAccessor( DBACCESSOR_PARAMETERDATA, 1, ¶meterBinding, sizeof(ParameterData), ¶meterHandle, ¶meterBindStatus); if (FAILED(result) || parameterBindStatus != DBBINDSTATUS_OK) { if (SUCCEEDED(result)) result = E_FAIL; break; } ParameterData parameter = { DBSTATUS_S_OK, sizeof(LONG), 0 }; DBPARAMS parameters = { ¶meter, 1, parameterHandle }; result = commandText->Execute( nullptr, IID_IRowset, ¶meters, nullptr, reinterpret_cast<IUnknown**>(&rowset)); if (FAILED(result)) break; result = rowset->QueryInterface( IID_IAccessor, reinterpret_cast<void**>(&rowAccessor)); if (FAILED(result)) break; DBBINDING rowBindings[2] = {}; rowBindings[0].iOrdinal = 1; rowBindings[0].obStatus = offsetof(RowData, productIdStatus); rowBindings[0].obLength = offsetof(RowData, productIdLength); rowBindings[0].obValue = offsetof(RowData, productId); rowBindings[0].dwPart = DBPART_STATUS | DBPART_LENGTH | DBPART_VALUE; rowBindings[0].dwMemOwner = DBMEMOWNER_CLIENTOWNED; rowBindings[0].eParamIO = DBPARAMIO_NOTPARAM; rowBindings[0].cbMaxLen = sizeof(LONG); rowBindings[0].wType = DBTYPE_I4; rowBindings[0].bPrecision = 10; rowBindings[1].iOrdinal = 2; rowBindings[1].obStatus = offsetof(RowData, nameStatus); rowBindings[1].obLength = offsetof(RowData, nameLength); rowBindings[1].obValue = offsetof(RowData, name); rowBindings[1].dwPart = DBPART_STATUS | DBPART_LENGTH | DBPART_VALUE; rowBindings[1].dwMemOwner = DBMEMOWNER_CLIENTOWNED; rowBindings[1].eParamIO = DBPARAMIO_NOTPARAM; rowBindings[1].cbMaxLen = productNameCharacters * sizeof(wchar_t); rowBindings[1].wType = DBTYPE_WSTR; DBBINDSTATUS rowBindStatus[2] = { DBBINDSTATUS_OK, DBBINDSTATUS_OK }; result = rowAccessor->CreateAccessor( DBACCESSOR_ROWDATA, 2, rowBindings, sizeof(RowData), &rowHandle, rowBindStatus); if (FAILED(result) || rowBindStatus[0] != DBBINDSTATUS_OK || rowBindStatus[1] != DBBINDSTATUS_OK) { if (SUCCEEDED(result)) result = E_FAIL; break; } DBCOUNTITEM productsPrinted = 0; while (true) { result = rowset->GetNextRows( DB_NULL_HCHAPTER, 0, 1, &rowCount, &rows); if (FAILED(result) || rowCount == 0) break; RowData row = {}; result = rowset->GetData(rows[0], rowHandle, &row); if (FAILED(result) || row.productIdStatus != DBSTATUS_S_OK || row.productIdLength != sizeof(LONG) || row.nameStatus != DBSTATUS_S_OK || row.nameLength == 0 || row.nameLength % sizeof(wchar_t) != 0 || row.nameLength >= sizeof(row.name)) { result = E_FAIL; break; } row.name[row.nameLength / sizeof(wchar_t)] = L'\0'; if (productsPrinted == 0) { std::wcout << L"Connected with MSOLEDBSQL19.\n\n"; std::wcout << std::left << std::setw(12) << L"Product ID" << L"Name\n"; std::wcout << std::setw(12) << L"----------" << L"----\n"; } std::wcout << std::left << std::setw(12) << row.productId << row.name << L'\n'; ++productsPrinted; result = rowset->ReleaseRows( rowCount, rows, nullptr, nullptr, nullptr); CoTaskMemFree(rows); rows = nullptr; rowCount = 0; if (FAILED(result)) break; } if (FAILED(result)) break; if (productsPrinted == 0) { result = E_FAIL; break; } } while (false); if (rows != nullptr) { if (rowset != nullptr && rowCount != 0) rowset->ReleaseRows(rowCount, rows, nullptr, nullptr, nullptr); CoTaskMemFree(rows); } if (rowHandle != DB_NULL_HACCESSOR && rowAccessor != nullptr) rowAccessor->ReleaseAccessor(rowHandle, nullptr); if (parameterHandle != DB_NULL_HACCESSOR && parameterAccessor != nullptr) parameterAccessor->ReleaseAccessor(parameterHandle, nullptr); Release(rowAccessor); Release(rowset); Release(parameterAccessor); Release(commandParameters); Release(commandText); Release(createCommand); Release(createSession); if (initialized) dbInitialize->Uninitialize(); Release(dbInitialize); Release(dataInitialize); CoUninitialize(); if (FAILED(result)) { std::wcerr << L"OLE DB operation failed: 0x" << std::hex << result << L'\n'; return 1; } return 0; }
La stringa di connessione viene passata a IDataInitialize::GetDataSource. Questa API usa i nomi di parole chiave con spazi Use Encryption for Data e Trust Server Certificate. Le stringhe di connessione richiedono la crittografia e richiedono la validazione dei certificati.
La query utilizza un punto interrogativo come indicatore del parametro. L'applicazione associa l'ID prodotto minimo 0 come valore int di SQL Server, legge fino a cinque righe da SalesLT.Product e stampa l'ID prodotto e il nome.
Compilare ed eseguire l'applicazione
Nello stesso Prompt dei comandi di Native Tools x64, individua il file di intestazione dell'SDK OLE DB installato e memorizzane la directory in
OLEDB_INCLUDE:for /f "delims=" %i in ('where /r "%ProgramFiles%\Microsoft SQL Server\Client SDK\OLEDB" msoledbsql.h') do for %j in ("%~dpi.") do set "OLEDB_INCLUDE=%~fj"Visualizza la directory selezionata e verifica che contenga l'intestazione seguente:
echo %OLEDB_INCLUDE% dir "%OLEDB_INCLUDE%\msoledbsql.h"Compilare l'applicazione:
cl /std:c++17 /EHsc /W4 /I"%OLEDB_INCLUDE%" oledb-quickstart.cpp /link ole32.lib oleaut32.libEseguire l'applicazione:
oledb-quickstart.exeCancellare la stringa di connessione dal Prompt dei comandi corrente:
set OLEDB_CONNECTION_STRING= set OLEDB_USER_ID= set OLEDB_PASSWORD=
Le righe di prodotto possono variare a seconda della versione di AdventureWorksLT. L'output sarà simile al seguente esempio:
Connected with MSOLEDBSQL19.
Product ID Name
---------- ----
680 HL Road Frame - Black, 58
706 HL Road Frame - Red, 58
707 Sport-100 Helmet, Red
708 Sport-100 Helmet, Black
709 Mountain Bike Socks, M