Использование объектов ошибок OLE DB (SQL Server Compact)
При возникновении ошибки во время выполнения приложения SQL Server Compact 3.5 поставщик OLE DB для SQL Server Compact 3.5 возвращает и сохраняет массив объектов ошибок. Затем к этим объектам можно обращаться с помощью OLE DB обычным способом. Поставщик OLE DB для SQL Server Compact 3.5 возвращает ошибки для всех поддерживаемых интерфейсов. Дополнительные сведения см. в разделе Реализованные интерфейсы OLE DB (SQL Server Compact). Сведения об общем механизме извлечения клиентом OLE DB данных об ошибках см. в разделе Microsoft OLE DB документации по пакету разработки ПО с помощью компонентов доступа к данным Microsoft MDAC в библиотеке MSDN.
Примеры
В приведенном примере показан способ извлечения специфических для поставщика номеров ошибок при использовании поставщика OLE DB для SQL Server Compact 3.5.
Примечание
Чтобы запустить этот образец приложения, необходимо зарегистрировать библиотеку sqlceoledb35.dll. В Windows это можно сделать в командной строке при помощи программы regsvr32.
Примечание
CLSID_SQLSERVERCE — макрос, заданный в файле заголовка OLEDB и соответствующий значению CLSID_SQLSERVERCE_3_5.
#include <windows.h>
#include <sqlce_oledb.h>
#include <sqlce_err.h>
#include <stdio.h>
/// <summary>
/// This function demonstrates a routine that can handle and display
/// errors from the OLE DB provider for SQL Server Compact 3.5. The
/// errors that occured on the current thread are displayed.
/// </summary>
HRESULT DisplayCurrentThreadErrors()
{
static TCHAR *sErrIErrorInfo = L"IErrorInfo interface";
static TCHAR *sErrIErrorRecords = L"IErrorRecords interface";
static TCHAR *sErrRecordCount = L"error record count";
static TCHAR *sErrInfo = L"ERRORINFO structure";
static TCHAR *sErrStandardInfo = L"standard error info";
static TCHAR *sErrDescription = L"standard error description";
static TCHAR *sErrNoSource = L"error source";
HRESULT hr = S_OK;
IErrorInfo *pIErrorInfo = NULL;
IErrorRecords *pIErrorRecords = NULL;
ERRORINFO errorInfo = { 0 };
IErrorInfo *pIErrorInfoRecord = NULL;
try
{
// This interface supports returning error information.
// Get the error object from the system for the current
// thread.
hr = GetErrorInfo(0, &pIErrorInfo);
if ( hr == S_FALSE )
{
wprintf(L"No error occured.\n");
return S_OK;
}
if(FAILED(hr) || NULL == pIErrorInfo)
throw sErrIErrorInfo;
// The error records are retrieved from the IIErrorRecords
// interface, which can be obtained from the IErrorInfo
// interface.
hr = pIErrorInfo->QueryInterface(IID_IErrorRecords,
(void **) &pIErrorRecords);
if ( FAILED(hr) || NULL == pIErrorRecords )
throw sErrIErrorRecords;
// The IErrorInfo interface is no longer required because
// we have the IErrorRecords interface, relase it.
pIErrorInfo->Release();
pIErrorInfo = NULL;
ULONG ulNumErrorRecs = 0;
// Determine the number of records in this error object
hr = pIErrorRecords->GetRecordCount(&ulNumErrorRecs);
if ( FAILED(hr) )
throw sErrRecordCount;
// Loop over each error record in the error object to display
// information about each error. Errors are returned.
for (DWORD dwErrorIndex = 0;
dwErrorIndex < ulNumErrorRecs;
dwErrorIndex++)
{
// Retrieve basic error information for this error.
hr = pIErrorRecords->GetBasicErrorInfo(dwErrorIndex,
&errorInfo);
if ( FAILED(hr) )
throw sErrInfo;
TCHAR szCLSID[64] = { 0 };
TCHAR szIID[64] = { 0 };
TCHAR szDISPID[64] = { 0 };
StringFromGUID2(errorInfo.clsid, (LPOLESTR)szCLSID,
sizeof(szCLSID));
StringFromGUID2(errorInfo.iid, (LPOLESTR)szIID,
sizeof(szIID));
wprintf(L"HRESULT = %lx\n", errorInfo.hrError);
wprintf(L"clsid = %s\n", szCLSID);
wprintf(L"iid = %s\n", szIID);
wprintf(L"dispid = %ld\n", errorInfo.dispid);
wprintf(L"Native Error Code = %lx\n", errorInfo.dwMinor);
// Retrieve standard error information for this error.
hr = pIErrorRecords->GetErrorInfo(dwErrorIndex, NULL,
&pIErrorInfoRecord);
if ( FAILED(hr) )
throw sErrStandardInfo;
BSTR bstrDescriptionOfError;
BSTR bstrSourceOfError;
// Get the description of the error.
hr = pIErrorInfoRecord->GetDescription(
&bstrDescriptionOfError);
if ( FAILED(hr) )
throw sErrDescription;
wprintf(L"Description = %s\n", bstrDescriptionOfError);
// Get the source of the error.
hr = pIErrorInfoRecord->GetSource(&bstrSourceOfError);
if ( FAILED(hr) )
throw sErrNoSource;
wprintf(L"Description = %s\n", bstrSourceOfError);
// This interface variable will be used the next time
// though this loop. In the last error case this interface
// is no longer needed so we must release it.
if(NULL != pIErrorInfoRecord)
pIErrorInfoRecord->Release();
pIErrorInfoRecord = NULL;
}
}
catch( TCHAR *szMsg )
{
wprintf(L"Failed to retrieve ");
wprintf(szMsg);
}
if( pIErrorInfoRecord )
pIErrorInfoRecord->Release();
if ( pIErrorInfo )
pIErrorInfo->Release();
if ( pIErrorRecords )
pIErrorRecords->Release();
return hr;
}
/// <summary>
/// This called will try to connect to a non existant
/// database to cause an error condition so that the call
/// to DisplayCurrentThreadError() has some errors to
/// display.
/// </summary>
/// <param="pIDBProperties">
/// IDBProperties interface that is used to set the properties on
/// for the Sql Compact engine object.
/// </param>
/// <param="pIDBInitialize">
/// Interface to the Sql Compact initialization object.
/// </param>
void CreateErrorCondition(IDBProperties *pIDBProperties,
IDBInitialize *pIDBInitialize)
{
HRESULT hr = S_OK;
DBPROP dbprop[1];
DBPROPSET dbpropset[1];
VariantInit(&dbprop[0].vValue);
// Initialize a property that uses name of database.
dbprop[0].dwPropertyID = DBPROP_INIT_DATASOURCE;
dbprop[0].dwOptions = DBPROPOPTIONS_REQUIRED;
dbprop[0].vValue.vt = VT_BSTR;
dbprop[0].vValue.bstrVal = SysAllocString(L"t@#$94.SC5");
// Initialize the property set.
dbpropset[0].guidPropertySet = DBPROPSET_DBINIT;
dbpropset[0].rgProperties = dbprop;
dbpropset[0].cProperties = sizeof(dbprop)/sizeof(dbprop[0]);
hr = pIDBProperties->SetProperties(
sizeof(dbpropset)/sizeof(dbpropset[0]),
dbpropset);
VariantClear(&dbprop[0].vValue);
if( FAILED(hr) )
return;
SysFreeString(dbprop[0].vValue.bstrVal);
// This call will fail because the db does not exit.
pIDBInitialize->Initialize();
}
/// <summary>
/// Application entry point initializes and cleans up the
/// needed interfaces and then calls the
/// DisplayCurrentThreadErrors() function to display error
/// information for the main application thread.
/// </summary>
void main()
{
HRESULT hr = S_OK;
IDBProperties *pIDBProperties = NULL;
ISupportErrorInfo *pISupportErrorInfo = NULL;
IDBInitialize *pIDBInitialize = NULL;
BOOL bComInitialized = FALSE;
try
{
hr = CoInitialize(NULL);
if ( FAILED(hr) )
{
wprintf(L"CoInitialize failed");
throw hr;
}
bComInitialized = TRUE;
// Retrieve the SQL Compact edition initialization interface.
hr = CoCreateInstance(CLSID_SQLSERVERCE,
0,
CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void**)&pIDBInitialize);
if( FAILED(hr) || NULL == pIDBInitialize )
{
wprintf(L"Failed to retrieve IDBInitialize Interface");
throw hr;
}
// Retrieve the property interface, This interface will enable
// setting of specific propertes on the SQL Server Compact
// engine object.
hr = CoCreateInstance(CLSID_SQLSERVERCE,
0,
CLSCTX_INPROC_SERVER,
IID_IDBProperties,
(void**) &pIDBProperties);
if( FAILED(hr) || NULL == pIDBProperties )
{
wprintf(L"Failed to retrieve IDBProperties Interface");
throw hr;
}
hr = pIDBProperties->QueryInterface(IID_ISupportErrorInfo,
(void**)&pISupportErrorInfo);
if( FAILED(hr) || NULL == pISupportErrorInfo )
{
wprintf(L"Interface does not support ISupportErrorInfo");
throw hr;
}
// Create an error condition by trying to open a non existance
// datafile.
CreateErrorCondition(pIDBProperties, pIDBInitialize);
// Display errors that occured on the current (main) thread.
hr = DisplayCurrentThreadErrors();
if ( FAILED(hr) )
throw hr;
}
catch( HRESULT hr)
{
wprintf(L", Error Code: %lx\n", hr);
}
if ( pISupportErrorInfo )
pISupportErrorInfo->Release();
if ( pIDBProperties )
pIDBProperties->Release();
if ( pIDBInitialize )
pIDBInitialize->Release();
if ( bComInitialized )
CoUninitialize();
}