Persisted Data Source Objects in SQL Server Native Client
Applies to: SQL Server Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW)
Important
The SQL Server Native Client (often abbreviated SNAC) has been removed from SQL Server 2022 (16.x) and SQL Server Management Studio 19 (SSMS). Both the SQL Server Native Client OLE DB provider (SQLNCLI or SQLNCLI11) and the legacy Microsoft OLE DB Provider for SQL Server (SQLOLEDB) are not recommended for new development. Switch to the new Microsoft OLE DB Driver (MSOLEDBSQL) for SQL Server going forward.
The SQL Server Native Client OLE DB provider supports persisted data source objects with the IPersistFile interface.
Examples
A. Persist data source initialization:
This example shows a function that persists data source initialization properties defining a server, database, and the use of the Windows Authentication Mode for connection. The server name and database name are received in the pLocation and pDatasource parameters of the function.
HRESULT SetAndSaveInitProps
(
IDBInitialize* pIDBInitialize,
WCHAR* pDataSource,
WCHAR* pCatalog,
BOOL bUseWinNTAuth
)
{
const ULONG nProps = 4;
ULONG nSSProps;
ULONG nPropSets;
ULONG nProp;
IDBProperties* pIDBProperties = NULL;
IPersistFile* pIPersistFile = NULL;
DBPROP aInitProps[nProps];
DBPROP* aSSInitProps = NULL;
DBPROPSET* aInitPropSets = NULL;
HRESULT hr;
nSSProps = 0;
nPropSets = 1;
aInitPropSets = new DBPROPSET[nPropSets];
// Initialize common property options.
for (nProp = 0; nProp < nProps; nProp++)
{
VariantInit(&aInitProps[nProp].vValue);
aInitProps[nProp].dwOptions = DBPROPOPTIONS_REQUIRED;
aInitProps[nProp].colid = DB_NULLID;
}
// Level of prompting that will be done to complete the connection
// process.
aInitProps[0].dwPropertyID = DBPROP_INIT_PROMPT;
aInitProps[0].vValue.vt = VT_I2;
aInitProps[0].vValue.iVal = DBPROMPT_NOPROMPT;
// Server name.
aInitProps[1].dwPropertyID = DBPROP_INIT_DATASOURCE;
aInitProps[1].vValue.vt = VT_BSTR;
aInitProps[1].vValue.bstrVal = SysAllocString(pDataSource);
// Database.
aInitProps[2].dwPropertyID = DBPROP_INIT_CATALOG;
aInitProps[2].vValue.vt = VT_BSTR;
aInitProps[2].vValue.bstrVal = SysAllocString(pCatalog);
aInitProps[3].dwPropertyID = DBPROP_AUTH_INTEGRATED;
if (bUseWinNTAuth == TRUE)
{
aInitProps[3].vValue.vt = VT_BSTR;
aInitProps[3].vValue.bstrVal = SysAllocString(L"SSPI");
} //end if
// Now that properties are set, construct the PropertySet array.
aInitPropSets[0].guidPropertySet = DBPROPSET_DBINIT;
aInitPropSets[0].cProperties = nProps;
aInitPropSets[0].rgProperties = aInitProps;
// Set initialization properties
pIDBInitialize->QueryInterface(IID_IDBProperties,
(void**) &pIDBProperties);
hr = pIDBProperties->SetProperties(nPropSets, aInitPropSets);
if (FAILED(hr))
{
// Display error from failed SetProperties.
}
pIDBProperties->Release();
// Free references on OLE known strings.
for (nProp = 0; nProp < nProps; nProp++)
{
if (aInitProps[nProp].vValue.vt == VT_BSTR)
SysFreeString(aInitProps[nProp].vValue.bstrVal);
}
for (nProp = 0; nProp < nSSProps; nProp++)
{
if (aSSInitProps[nProp].vValue.vt == VT_BSTR)
SysFreeString(aSSInitProps[nProp].vValue.bstrVal);
}
// Free dynamically allocated memory.
delete [] aInitPropSets;
delete [] aSSInitProps;
// On success, persist the data source.
if (SUCCEEDED(hr))
{
pIDBInitialize->QueryInterface(IID_IPersistFile,
(void**) &pIPersistFile);
hr = pIPersistFile->Save(OLESTR("MyDataSource.txt"), FALSE);
if (FAILED(hr))
{
// Display errors from IPersistFile interface.
}
pIPersistFile->Release();
}
return (hr);
}
B. Use persisted data source initialization:
This example uses a persisted data source object with additional initialization properties that provide a SQL Server login and password.
HRESULT InitFromPersistedDS
(
IDBInitialize* pIDBInitialize,
WCHAR* pPersistedDSN,
WCHAR* pUID,
WCHAR* pPWD
)
{
//const ULONG nProps = 3;
const ULONG nProps = 1;
const ULONG nPropSets = 1;
ULONG nProp;
IDBProperties* pIDBProperties = NULL;
IPersistFile* pIPersistFile = NULL;
DBPROP aInitProps[nProps];
DBPROPSET aInitPropSets[nPropSets];
HRESULT hr;
// First load the persisted data source information.
pIDBInitialize->QueryInterface(IID_IPersistFile,
(void**) &pIPersistFile);
hr = pIPersistFile->Load(pPersistedDSN, STGM_DIRECT);
if (FAILED(hr))
{
// Display errors from IPersistFile interface.
}
pIPersistFile->Release();
if (FAILED(hr))
{
return (hr);
}
// Initialize common property options.
for (nProp = 0; nProp < nProps; nProp++)
{
VariantInit(&aInitProps[nProp].vValue);
aInitProps[nProp].dwOptions = DBPROPOPTIONS_REQUIRED;
aInitProps[nProp].colid = DB_NULLID;
}
// Level of prompting that will be done to complete the connection
// process.
aInitProps[0].dwPropertyID = DBPROP_INIT_PROMPT;
aInitProps[0].vValue.vt = VT_I2;
aInitProps[0].vValue.iVal = DBPROMPT_NOPROMPT;
// Now that properties are set, construct the PropertySet array.
aInitPropSets[0].guidPropertySet = DBPROPSET_DBINIT;
aInitPropSets[0].cProperties = nProps;
aInitPropSets[0].rgProperties = aInitProps;
// Set initialization properties
pIDBInitialize->QueryInterface(IID_IDBProperties,
(void**) &pIDBProperties);
hr = pIDBProperties->SetProperties(nPropSets, aInitPropSets);
if (SUCCEEDED(hr))
{
hr = pIDBInitialize->Initialize();
if (FAILED(hr))
{
DumpError(pIDBInitialize, IID_IDBInitialize);
}
}
else
{
// Display error from failed SetProperties.
}
pIDBProperties->Release();
// Free references on OLE known strings.
for (nProp = 0; nProp < nProps; nProp++)
{
if (aInitProps[nProp].vValue.vt == VT_BSTR)
SysFreeString(aInitProps[nProp].vValue.bstrVal);
}
return (hr);
}
The IPersistFile::Save method can be called before or after calling IDBInitialize::Initialize. Calling the method after a successful return from IDBInitialize::Initialize ensures a valid data source specification is persisted.