前言:

鄙司原始用的都是ADO来访问数据库,而我现在着手的项目是从我的GPS历史数据库中,取出历时数据的一个接口,一个DLL.用ADO写完之后,测试下来,平均4000条的数据,需要 180 毫秒左右. 包括数据包的排序.领导说有点慢.他是用C#写的.

而后我查找了资料,决定用Native Client OLEDB来试一试. 测试之后,效果还不错.取4000条的数据,只花了50毫秒左右,足足快了三倍.当然这也包括了排序.

鉴于此外加OLEDB资料很少,把我的代码分享出来.

WO 对 OLEDB 进行了简单的封装. 以下是项目的OLEDB部分代码.

//NativeClientOLEDB.h

 #pragma once

 #include <oledb.h>
#include <oledberr.h>
#include <stdio.h>
#include <stddef.h> // for offsetof #include <msdaguid.h>
#include <msdasql.h>
#include <msdasc.h>
#include <sqlncli.h>
#include <string>
//#include "C:\Program Files\Microsoft SQL Server\110\SDK\Include\sqlncli.h" #ifndef _AUTHOR_NAME
#define _AUTHOR_NAME "沈春钟"
#define _CREATE_DATE "2016-05-18"
#define _LIBRARY_TITLE "NativeClientOLEDB"
#define _LIBRARY_DESC "对NaTiveClientOLEDB的封装"
#define _MAINTAIN_CONTACT "SamRichard@live.cn"
#define _MAX_COL_NUM 100
#endif #pragma comment(lib, "sqlncli11.lib") // @type UWORD | 2 byte unsigned integer.
typedef unsigned short UWORD; // @type SDWORD | 4 byte signed integer.
typedef signed long SDWORD; using namespace std; //委托表数据结构体
#pragma pack(push, 1)
class Data
{
//SDWORD SOID_len; // Length of data (not space allocated).
//DWORD SOID_status; // Status of column.
//int SOID_value;
};
#pragma pack(pop) //// How to lay out each column in memory.
//struct COLUMNDATA {
// SDWORD idLen; // Length of data (not space allocated).
// DWORD idStatus; // Status of column.
// int id; // Store data here as a variant.
// SDWORD dateLen;
// DWORD dateStatus;
// char date[21];
//}; class CNativeClientOLEDB
{
public:
CNativeClientOLEDB(void);
~CNativeClientOLEDB(void); public:
//初始化连接
HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG);
//不建议用此方式初始化
HRESULT Init(CStringW strConnectionString);
//释放连接
void UnInit(); protected:
//函数申明
virtual void set_bindings();
//设置每列数据列的类型
virtual void SetColType(void);
//设置每列数据列的长度
virtual void SetColLen(void); //bind one by one
void set_bind(DBBINDING &binding, int col, DBBYTEOFFSET len_offset, DBBYTEOFFSET status_offset, DBBYTEOFFSET value_offset, DBLENGTH len, DBTYPE type); void DumpErrorInfo(IUnknown* pObjectWithError, REFIID IID_InterfaceWithError); //HRESULT FastInsertData();
//快速查询数据
HRESULT FastQueryData(CStringW strSql,ULONG& nColNum, IRowset** pIRowset,IAccessor** pIAccessor, HACCESSOR& hAccessor);
//释放RowSet和IAccessor
HRESULT ReleaseRowsetAndIAccessor(IRowset** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor);
//快速插入数据
HRESULT FastInsertData(CStringW strTable, ULONG& nColNum, IRowsetFastLoad** pIRowsetFastLoad, IAccessor** pIAccessor, HACCESSOR& hAccessor);
//释放RowsetFast和IAccessor
HRESULT ReleaseRowsetFastLoadAndIAccessor(IRowsetFastLoad** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor); private: // Given an ICommand pointer, properties, and query, a rowsetpointer is returned.
HRESULT DBInitAndConnect(DBPROPSET* rgPropertySets, ULONG ulcPropCount, CLSID clsidProv); // Use to set properties and execute a given query.
HRESULT ExecuteQuery(IDBCreateCommand* pIDBCreateCommand,
WCHAR* pwszQuery,
DBPROPSET* rgPropertySets,
ULONG ulcPropCount,
LONG* pcRowsAffected,
IRowset** ppIRowset,
BOOL fSuccessOnly = TRUE); // Use to set up options for call to IDBInitialize::Initialize.
void SetupOption(DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp); // Sets fastload property on/off for session.
HRESULT SetFastLoadProperty(BOOL fSet); public:
//创建会话和命令
HRESULT CreateSessionAndCommand();
//释放会话和命令
HRESULT ReleaseSessionAndCommand();
//设置模式和创建会话
HRESULT SetPropertiesAndCreateSessionAndIOpenRowset(BOOL bFast = TRUE);
//释放会话
HRESULT ReleaseSessionIOpenRowset(); private:
//初始化层
IMalloc* m_pIMalloc;
IDataInitialize* m_pIDataInitialize;
IDBInitialize* m_pIDBInitialize;
// OLE initialized?
BOOL m_bInitialized;
//回话和命令层
IDBCreateSession* m_pIDBSession;
IOpenRowset* m_pIOpenRowset;
ICommand* m_pICommand;
IDBCreateCommand* m_pIDBCreateCommand;
ICommandText* m_pICommandText;
DBID TableID; protected:
//binding数组
DBBINDING m_bindings[_MAX_COL_NUM]; //委托表每列的数据类型
DBTYPEENUM col_type[_MAX_COL_NUM]; //委托表每列的数据长度
DBBYTEOFFSET col_len[_MAX_COL_NUM];
};

//NativeClientOLEDB.cpp

 #include "StdAfx.h"
#include "NativeClientOLEDB.h"
#include <time.h>
#include <Base64.h> #define COUNT 10000
#define ROW_SIZE 1000 #define COLUMN_ALIGNVAL 8
#define ROUND_UP(Size, Amount)(((DWORD)(Size) + ((Amount)-1)) & ~((Amount)-1)) const UWORD g_cOPTION = ;
const UWORD MAXPROPERTIES = ;
const ULONG DEFAULT_CBMAXLENGTH = ; CNativeClientOLEDB::CNativeClientOLEDB(void)
{
m_pIMalloc = NULL;
m_pIDBInitialize = NULL;
m_bInitialized = FALSE;
m_pIDBSession = NULL;
m_pIOpenRowset = NULL;
m_pICommand = NULL;
m_pIDBCreateCommand = NULL;
m_pICommandText = NULL;
TableID.uName.pwszName = NULL;
m_pIDataInitialize = NULL;
SetColType();
SetColLen();
} CNativeClientOLEDB::~CNativeClientOLEDB(void)
{
ReleaseSessionAndCommand();
UnInit();
} HRESULT CNativeClientOLEDB::Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG)
{
HRESULT hr = NOERROR;
// One property set for initializing.
DBPROPSET rgPropertySets[];
// Properties within above property set.
DBPROP rgDBProperties[g_cOPTION];
do
{
// Basic initialization.
if (FAILED(CoInitialize(NULL)))
break;
else
m_bInitialized = TRUE; hr = CoGetMalloc(MEMCTX_TASK, &m_pIMalloc);
if ((!m_pIMalloc) || FAILED(hr))
break; // Set up property set for call to IDBInitialize in CreateSessionCommand.
rgPropertySets[].rgProperties = rgDBProperties;
rgPropertySets[].cProperties = g_cOPTION;
rgPropertySets[].guidPropertySet = DBPROPSET_DBINIT; SetupOption(DBPROP_INIT_DATASOURCE, (WCHAR *)(LPCWSTR)strDataSource, &rgDBProperties[]);
SetupOption(DBPROP_INIT_CATALOG, (WCHAR *)(LPCWSTR)strCataLOG, &rgDBProperties[]);
SetupOption(DBPROP_AUTH_USERID, (WCHAR *)(LPCWSTR)strUserID, &rgDBProperties[]);
SetupOption(DBPROP_AUTH_PASSWORD, (WCHAR *)(LPCWSTR)strPassWD, &rgDBProperties[]); //if (S_OK != (hr = DBInitAndConnect(rgPropertySets, 1, SQLNCLI_CLSID)))
if (S_OK != (hr = DBInitAndConnect(rgPropertySets, , CLSID_SQLNCLI11)))
break;
return S_OK;
} while (); return hr;
} HRESULT CNativeClientOLEDB::Init(CStringW strConnectionString)
{
HRESULT hr = S_OK;
do
{ if (FAILED(CoInitialize(NULL)))
break;
else
m_bInitialized = TRUE; hr = CoCreateInstance(
CLSID_MSDAINITIALIZE,
NULL,
CLSCTX_INPROC_SERVER,
IID_IDataInitialize,
reinterpret_cast<LPVOID *>(&m_pIDataInitialize));
if (!SUCCEEDED(hr))
break; hr = m_pIDataInitialize->GetDataSource(
NULL,
CLSCTX_INPROC_SERVER,
strConnectionString,
IID_IDBInitialize,
reinterpret_cast<IUnknown **>(&m_pIDBInitialize)); if (!SUCCEEDED(hr))
break; if (!SUCCEEDED(hr = m_pIDBInitialize->Initialize())) {
printf("Call to initialize failed.\n");
break;
} return S_OK; } while (); UnInit();
return hr;
} void CNativeClientOLEDB::UnInit()
{
HRESULT hr = NOERROR; //ReleaseSessionAndCommand();
//ReleaseSessionIOpenRowset(); if (m_pIMalloc){
m_pIMalloc->Release();
m_pIMalloc = NULL;
} if (m_pIDBInitialize) {
hr = m_pIDBInitialize->Uninitialize();
m_pIDBInitialize = NULL;
if (FAILED(hr))
printf("Uninitialize failed\n");
} if (m_bInitialized){
CoUninitialize();
m_bInitialized = FALSE;
} if (SUCCEEDED(hr))
printf("Test completed successfully.\n\n");
else
printf("Test failed.\n\n"); } void CNativeClientOLEDB::SetColType(void)
{ } void CNativeClientOLEDB::SetColLen(void)
{ } void CNativeClientOLEDB::set_bindings()
{ } void CNativeClientOLEDB::set_bind(DBBINDING &binding, int col, DBBYTEOFFSET len_offset, DBBYTEOFFSET status_offset, DBBYTEOFFSET value_offset, DBLENGTH len, DBTYPE type)
{
binding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
binding.iOrdinal = col;
binding.pTypeInfo = NULL;
binding.obValue = value_offset;
binding.obLength = len_offset;
binding.obStatus = status_offset;
binding.cbMaxLen = len; // Size of varchar column.
binding.pTypeInfo = NULL;
binding.pObject = NULL;
binding.pBindExt = NULL;
binding.dwFlags = ;
binding.eParamIO = DBPARAMIO_NOTPARAM;
binding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
binding.bPrecision = ;
binding.bScale = ;
binding.wType = type;
} HRESULT CNativeClientOLEDB::DBInitAndConnect(DBPROPSET* rgPropertySets, ULONG ulcPropCount, CLSID clsidProv)
{
HRESULT hr = NOERROR;
IDBProperties* pIDBProperties = NULL;
UWORD i = , j = ; // indexes. if (ulcPropCount && !rgPropertySets) {
hr = E_INVALIDARG;
return hr;
} if (S_OK != (hr = CoCreateInstance(clsidProv,
NULL, CLSCTX_INPROC_SERVER,
IID_IDBInitialize,
(void **)&m_pIDBInitialize))){
goto CLEANUP;
} if (S_OK != (hr = m_pIDBInitialize->QueryInterface(IID_IDBProperties,
(void **)&pIDBProperties)))
goto CLEANUP; if (S_OK != (hr = pIDBProperties->SetProperties(ulcPropCount, rgPropertySets))){
goto CLEANUP;
} if (S_OK != (hr = m_pIDBInitialize->Initialize())) { printf("Call to initialize failed.\n");
goto CLEANUP;
} CLEANUP:
if (pIDBProperties)
pIDBProperties->Release(); for (i = ; i < ulcPropCount; i++)
for (j = ; j < rgPropertySets[i].cProperties; j++)
VariantClear(&(rgPropertySets[i].rgProperties[j]).vValue);
return hr;
} void CNativeClientOLEDB::DumpErrorInfo(IUnknown* pObjectWithError, REFIID IID_InterfaceWithError)
{
// Interfaces used in the example.
IErrorInfo* pIErrorInfoAll = NULL;
IErrorInfo* pIErrorInfoRecord = NULL;
IErrorRecords* pIErrorRecords = NULL;
ISupportErrorInfo* pISupportErrorInfo = NULL;
ISQLErrorInfo* pISQLErrorInfo = NULL;
ISQLServerErrorInfo* pISQLServerErrorInfo = NULL; // Number of error records.
ULONG nRecs;
ULONG nRec; // Basic error information from GetBasicErrorInfo.
ERRORINFO errorinfo; // IErrorInfo values.
BSTR bstrDescription;
BSTR bstrSource; // ISQLErrorInfo parameters.
BSTR bstrSQLSTATE;
LONG lNativeError; // ISQLServerErrorInfo parameter pointers.
SSERRORINFO* pSSErrorInfo = NULL;
OLECHAR* pSSErrorStrings = NULL; // Hard-code an American English locale for the example.
DWORD MYLOCALEID = 0x0409; // Only ask for error information if the interface supports
// it.
if (FAILED(pObjectWithError->QueryInterface(IID_ISupportErrorInfo,
(void**)&pISupportErrorInfo)))
{
wprintf_s(L"SupportErrorErrorInfo interface not supported");
return;
}
if (FAILED(pISupportErrorInfo->
InterfaceSupportsErrorInfo(IID_InterfaceWithError)))
{
wprintf_s(L"InterfaceWithError interface not supported");
return;
} // Do not test the return of GetErrorInfo. It can succeed and return
// a NULL pointer in pIErrorInfoAll. Simply test the pointer.
GetErrorInfo(, &pIErrorInfoAll); if (pIErrorInfoAll != NULL)
{
// Test to see if it's a valid OLE DB IErrorInfo interface
// exposing a list of records.
if (SUCCEEDED(pIErrorInfoAll->QueryInterface(IID_IErrorRecords,
(void**)&pIErrorRecords)))
{
pIErrorRecords->GetRecordCount(&nRecs); // Within each record, retrieve information from each
// of the defined interfaces.
for (nRec = ; nRec < nRecs; nRec++)
{
// From IErrorRecords, get the HRESULT and a reference
// to the ISQLErrorInfo interface.
pIErrorRecords->GetBasicErrorInfo(nRec, &errorinfo);
pIErrorRecords->GetCustomErrorObject(nRec,
IID_ISQLErrorInfo, (IUnknown**)&pISQLErrorInfo); // Display the HRESULT, then use the ISQLErrorInfo.
wprintf_s(L"HRESULT:\t%#X\n", errorinfo.hrError); if (pISQLErrorInfo != NULL)
{
pISQLErrorInfo->GetSQLInfo(&bstrSQLSTATE,
&lNativeError); // Display the SQLSTATE and native error values.
wprintf_s(L"SQLSTATE:\t%s\nNative Error:\t%ld\n",
bstrSQLSTATE, lNativeError); // SysFree BSTR references.
SysFreeString(bstrSQLSTATE); // Get the ISQLServerErrorInfo interface from
// ISQLErrorInfo before releasing the reference.
pISQLErrorInfo->QueryInterface(
IID_ISQLServerErrorInfo,
(void**)&pISQLServerErrorInfo); pISQLErrorInfo->Release();
} // Test to ensure the reference is valid, then
// get error information from ISQLServerErrorInfo.
if (pISQLServerErrorInfo != NULL)
{
pISQLServerErrorInfo->GetErrorInfo(&pSSErrorInfo,
&pSSErrorStrings); // ISQLServerErrorInfo::GetErrorInfo succeeds
// even when it has nothing to return. Test the
// pointers before using.
if (pSSErrorInfo)
{
// Display the state and severity from the
// returned information. The error message comes
// from IErrorInfo::GetDescription.
wprintf_s(L"Error state:\t%d\nSeverity:\t%d\n",
pSSErrorInfo->bState,
pSSErrorInfo->bClass); // IMalloc::Free needed to release references
// on returned values. For the example, assume
// the g_pIMalloc pointer is valid.
m_pIMalloc->Free(pSSErrorStrings);
m_pIMalloc->Free(pSSErrorInfo);
} pISQLServerErrorInfo->Release();
} if (SUCCEEDED(pIErrorRecords->GetErrorInfo(nRec,
MYLOCALEID, &pIErrorInfoRecord)))
{
// Get the source and description (error message)
// from the record's IErrorInfo.
pIErrorInfoRecord->GetSource(&bstrSource);
pIErrorInfoRecord->GetDescription(&bstrDescription); if (bstrSource != NULL)
{
wprintf_s(L"Source:\t\t%s\n", bstrSource);
SysFreeString(bstrSource);
}
if (bstrDescription != NULL)
{
wprintf_s(L"Error message:\t%s\n",
bstrDescription);
SysFreeString(bstrDescription);
} pIErrorInfoRecord->Release();
}
} pIErrorRecords->Release();
}
else
{
// IErrorInfo is valid; get the source and
// description to see what it is.
pIErrorInfoAll->GetSource(&bstrSource);
pIErrorInfoAll->GetDescription(&bstrDescription); if (bstrSource != NULL)
{
wprintf_s(L"Source:\t\t%s\n", bstrSource);
SysFreeString(bstrSource);
}
if (bstrDescription != NULL)
{
wprintf_s(L"Error message:\t%s\n", bstrDescription);
SysFreeString(bstrDescription);
}
} pIErrorInfoAll->Release();
}
else
{
wprintf_s(L"GetErrorInfo failed.");
} pISupportErrorInfo->Release(); return;
} void CNativeClientOLEDB::SetupOption(DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp)
{
pDBProp->dwPropertyID = PropID;
pDBProp->dwOptions = DBPROPOPTIONS_REQUIRED;
pDBProp->colid = DB_NULLID;
pDBProp->vValue.vt = VT_BSTR;
pDBProp->vValue.bstrVal = SysAllocStringLen(wszVal, wcslen(wszVal));
} HRESULT CNativeClientOLEDB::SetFastLoadProperty(BOOL fSet)
{
HRESULT hr = S_OK;
IDBProperties* pIDBProps = NULL;
DBPROP rgProps[];
DBPROPSET PropSet; VariantInit(&rgProps[].vValue); rgProps[].dwOptions = DBPROPOPTIONS_REQUIRED;
rgProps[].colid = DB_NULLID;
rgProps[].vValue.vt = VT_BOOL;
rgProps[].dwPropertyID = SSPROP_ENABLEFASTLOAD; if (fSet == TRUE)
rgProps[].vValue.boolVal = VARIANT_TRUE;
else
rgProps[].vValue.boolVal = VARIANT_FALSE; PropSet.rgProperties = rgProps;
PropSet.cProperties = ;
PropSet.guidPropertySet = DBPROPSET_SQLSERVERDATASOURCE; if (SUCCEEDED(hr = m_pIDBInitialize->QueryInterface(IID_IDBProperties, (LPVOID *)&pIDBProps)))
hr = pIDBProps->SetProperties(, &PropSet); VariantClear(&rgProps[].vValue); if (pIDBProps)
pIDBProps->Release(); return hr;
} HRESULT CNativeClientOLEDB::FastQueryData(CStringW strSql,ULONG& nColNum,IRowset** pIRowset,IAccessor** pIAccessor, HACCESSOR& hAccessor)
{ HRESULT hr = E_FAIL;
if (NULL != *pIRowset || NULL != *pIAccessor || strSql.IsEmpty() || NULL == m_pICommandText || NULL == m_pICommand || nColNum <= ){
return hr;
}
do
{
if (FAILED(hr = m_pICommandText->SetCommandText(DBGUID_DBSQL, strSql))){
break;
} LONG lAffected;
if (FAILED(hr = m_pICommand->Execute(NULL, IID_IRowset, NULL, &lAffected, (IUnknown **)pIRowset))){
break;
} if (FAILED(hr = (*pIRowset)->QueryInterface(IID_IAccessor, (void **)pIAccessor))){
break;
} set_bindings(); DBBINDSTATUS dbs[_MAX_COL_NUM] = { };
if (FAILED(hr = (*pIAccessor)->CreateAccessor(DBACCESSOR_ROWDATA, (DBCOUNTITEM)nColNum, m_bindings, sizeof(Data),&hAccessor, dbs))){
//dbs是绑定状态
break;
} return S_OK;
} while (); ReleaseRowsetAndIAccessor(pIRowset, pIAccessor, hAccessor);
} HRESULT CNativeClientOLEDB::FastInsertData(CStringW strTable, ULONG& nColNum, IRowsetFastLoad** pIRowsetFastLoad, IAccessor** pIAccessor, HACCESSOR& hAccessor)
{
HRESULT hr = E_FAIL;
TableID.uName.pwszName = NULL;
TableID.eKind = DBKIND_NAME;
TableID.uName.pwszName = new WCHAR[strTable.GetLength() + ];
wcsncpy_s(TableID.uName.pwszName, strTable.GetLength() + , strTable, strTable.GetLength() + );
TableID.uName.pwszName[strTable.GetLength() + ] = (WCHAR)NULL; do
{
// Get IRowsetFastLoad initialized to use the test table.
if (FAILED(hr = m_pIOpenRowset->OpenRowset(NULL, &TableID, NULL, IID_IRowsetFastLoad, , NULL, (LPUNKNOWN *)pIRowsetFastLoad))){
break;
} set_bindings();
DBBINDSTATUS bds[_MAX_COL_NUM] = { };
if (FAILED(hr = (*pIRowsetFastLoad)->QueryInterface(IID_IAccessor, (void **)pIAccessor))){
break;
} if (FAILED(hr = (*pIAccessor)->CreateAccessor(DBACCESSOR_ROWDATA, (DBCOUNTITEM)nColNum, m_bindings, (ROUND_UP(sizeof(Data), COLUMN_ALIGNVAL)), &hAccessor, bds))){
//dbs是绑定状态
break;
} return S_OK;
} while (); ReleaseRowsetFastLoadAndIAccessor(pIRowsetFastLoad, pIAccessor, hAccessor);
return E_FAIL;
} HRESULT CNativeClientOLEDB::ReleaseRowsetAndIAccessor(IRowset** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor)
{
HRESULT hr = S_OK;
if (*pIRowset){
(*pIRowset)->Release();
(*pIRowset) = NULL;
} if (*pIAccessor && hAccessor){
if (FAILED((*pIAccessor)->ReleaseAccessor(hAccessor, NULL))){
hr = E_FAIL;
}
(*pIAccessor)->Release();
*pIAccessor = NULL;
} return hr;
} HRESULT CNativeClientOLEDB::ReleaseRowsetFastLoadAndIAccessor(IRowsetFastLoad** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor)
{ HRESULT hr = S_OK;
if (FAILED(hr = SetFastLoadProperty(FALSE)))
printf("SetFastLoadProperty(FALSE) failed with %x", hr); if (*pIAccessor && hAccessor)
if (FAILED((*pIAccessor)->ReleaseAccessor(hAccessor, NULL)))
hr = E_FAIL; if (*pIAccessor){
(*pIAccessor)->Release();
*pIAccessor = NULL;
} if (*pIRowset){
(*pIRowset)->Release();
(*pIRowset) = NULL;
} if (TableID.uName.pwszName)
delete[]TableID.uName.pwszName; return hr;
} HRESULT CNativeClientOLEDB::CreateSessionAndCommand()
{
HRESULT hr = E_FAIL;
if (NULL == m_pIDBInitialize || m_pIDBSession || m_pIOpenRowset || m_pIDBCreateCommand || m_pICommand || m_pICommandText){
return hr;
} do
{
if (FAILED(hr =
m_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void **)&m_pIDBSession)))
break; if (FAILED(hr =
m_pIDBSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown **)&m_pIOpenRowset )))
break; if (FAILED(hr = m_pIOpenRowset ->QueryInterface(IID_IDBCreateCommand, (void **)&m_pIDBCreateCommand))){
break;
} if (FAILED(hr = m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown **)&m_pICommand))){
break;
} if (FAILED(hr = m_pICommand->QueryInterface(&m_pICommandText))){
break;
} return S_OK; } while (); ReleaseSessionAndCommand();
return hr;
} HRESULT CNativeClientOLEDB::ReleaseSessionAndCommand()
{
HRESULT hr = S_OK;
if (m_pICommandText){
m_pICommandText->Release();
m_pICommandText = NULL;
} if (m_pICommand){
m_pICommand->Release();
m_pICommand = NULL;
} if (m_pIDBCreateCommand){
m_pIDBCreateCommand->Release();
m_pIDBCreateCommand = NULL;
} if (m_pIOpenRowset){
m_pIOpenRowset->Release();
m_pIOpenRowset = NULL;
} if (m_pIDBSession){
m_pIDBSession->Release();
m_pIDBSession = NULL;
} return S_OK;
} HRESULT CNativeClientOLEDB::SetPropertiesAndCreateSessionAndIOpenRowset(BOOL bFast /*= TRUE*/)
{
HRESULT hr;
if (NULL == m_pIDBInitialize){
return E_FAIL;
}
do
{
if (FAILED(hr = SetFastLoadProperty(bFast)))
break; if (FAILED(hr =
m_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void **)&m_pIDBSession)))
break; if (FAILED(hr =
m_pIDBSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown **)&m_pIOpenRowset)))
break; return S_OK;
} while ();
// Get the fastload pointer. ReleaseSessionIOpenRowset();
return E_FAIL;
} HRESULT CNativeClientOLEDB::ReleaseSessionIOpenRowset()
{
if (m_pIDBSession){
m_pIDBSession->Release();
m_pIDBSession = NULL;
} if (m_pIOpenRowset){
m_pIOpenRowset->Release();
m_pIOpenRowset = NULL;
}
return S_OK;
}

以上两个文件,基本覆盖了创建\连接\释放等等的过程.下面对某些函数进行讲解一下;

1. 调用CoInitialize 来初始化控件.因为它是基于com组件的.

2. 通过调用 CoCreateInstance 方法来创建数据源对象的实例。

每个 OLE DB 访问接口都具有一个唯一的类标识符 (CLSID)。 对于 SQL Server Native Client OLE DB 访问接口,类标识符为 CLSID_SQLNCLI10。 也可以使用符号 SQLNCLI_CLSID,该符号将解析为您引用的 sqlncli.h 中使用的 SQL Server Native Client OLE DB 访问接口。

数据源对象公开了 IDBProperties 接口,使用者使用该接口提供基本的身份验证信息,如服务器名、数据库名、用户 ID 和密码。 可调用IDBProperties::SetProperties 方法设置这些属性。

3.  调用 IDBProperties::Initialize 接口来建立与数据源的连接.

4. 在建立与某一数据源的连接后,使用者调用 IDBCreateSession::CreateSession 方法以创建一个会话。 该会话充当命令、行集或事务工厂。

5. IOpenRowset::OpenRowset 方法打开并返回一个行集,该行集包括来自单个基表或索引的所有行。

6. 执行IDBCreateCommand::CreateCommand 方法,以便为 ICommandText 接口创建一个命令对象和请求。

7. 利用 ICommandText::SetCommandText 指定要执行的命令。

当然在我的代码中有 set_bindings(); 这个函数是用来把数据库中的类型与OLEDB中的数据类型进行一个绑定. 可以参照:

https://msdn.microsoft.com/zh-cn/library/ms130984.aspx

8. 调用 Execute 命令用于执行该命令。

9. 从IRowset中取出数据等等操作.

10. 调用ReleaseRowsetAndIAccessor 来释放RowSet和IAccessor

11. 调用 ReleaseSessionAndCommand 来释放会话和命令

12. 最后调用UnInit 来释放连接.

上面是基于底层封装的数据源操作部分.下面给出与数据相关的操作的类.

//HistoryDataOLEDB.h

 #pragma once
#include <OLEDB/NativeClientOLEDB.h> #pragma pack(push, 1)
class HistoryData :
public Data{
public:
/*
SDWORD SOID_len; // Length of data (not space allocated).
DWORD SOID_status; // Status of column.
int SOID_value; SDWORD TerminalID_len; // Length of data (not space allocated).
DWORD TerminalID_status; // Status of column.
int TerminalID_value;
*/
SDWORD Longitude_len; // Length of data (not space allocated).
DWORD Longitude_status; // Status of column.
int Longitude_value; SDWORD Latitude_len; // Length of data (not space allocated).
DWORD Latitude_status; // Status of column.
int Latitude_value; SDWORD Speed_len; // Length of data (not space allocated).
DWORD Speed_status; // Status of column.
WORD Speed_value; // SDWORD Direction_len; // Length of data (not space allocated).
DWORD Direction_status; // Status of column.
WORD Direction_value; SDWORD Height_len; // Length of data (not space allocated).
DWORD Height_status; // Status of column.
short Height_value; SDWORD Lock_len; // Length of data (not space allocated).
DWORD Lock_status; // Status of column.
BYTE Lock_value; SDWORD Gpstime_len; // Length of data (not space allocated).
DWORD Gpstime_status; // Status of column.
char Gpstime_value[]; SDWORD InStatus_len; // Length of data (not space allocated).
DWORD InStatus_status; // Status of column.
short InStatus_value; //
SDWORD TmlStatus_len; // Length of data (not space allocated).
DWORD TmlStatus_status; // Status of column.
short TmlStatus_value; SDWORD WarnFlag_len; // Length of data (not space allocated).
DWORD WarnFlag_status; // Status of column.
short WarnFlag_value; SDWORD Resver2_len; // Length of data (not space allocated).
DWORD Resver2_status; // Status of column.
short Resver2_value; SDWORD Alldis_len; // Length of data (not space allocated).
DWORD Alldis_status; // Status of column.
int Alldis_value; SDWORD Temperature_len; // Length of data (not space allocated).
DWORD Temperature_status; // Status of column.
int Temperature_value; //
SDWORD Oil_len; // Length of data (not space allocated).
DWORD Oil_status; // Status of column.
short Oil_value; SDWORD Smsid1_len; // Length of data (not space allocated).
DWORD Smaid1_status; // Status of column.
short Smaid1_value; SDWORD Smaid2_len; // Length of data (not space allocated).
DWORD Smaid2_status; // Status of column.
short Smaid2_value;
/*
SDWORD Longitude2_len; // Length of data (not space allocated).
DWORD Longitude2_status; // Status of column.
int Longitude2_value; SDWORD Latitude2_len; // Length of data (not space allocated).
DWORD Latitude2_status; // Status of column.
int Latitude2_value;
*/
//
SDWORD AffixData_len; // Length of data (not space allocated).
DWORD AffixData_status; // Status of column.
char AffixData_value[];
};
#pragma pack(pop) class CHistoryDataOLEDB :
public CNativeClientOLEDB
{
public:
CHistoryDataOLEDB(void);
~CHistoryDataOLEDB(void); virtual void SetColType(void); virtual void SetColLen(void); virtual void set_bindings(); void Lock() { cs.Lock(); };
void Unlock() { cs.Unlock(); }; public:
//快速查询数据
LPBYTE FastQueryData(CStringW strSql,ULONG nColNum, int* nLen, int* nCount);
//快速插入数据
BOOL FastInsertData(const CStringW strTable, HistoryData* const pData, const int nDataNum); private:
CCriticalSection cs;
};

//HistoryDataOLEDB.cpp

 #include "StdAfx.h"
#include "HistoryDataOLEDB.h"
#include "HistoryDefine.h"
#include "Base64.h" CHistoryDataOLEDB::CHistoryDataOLEDB(void)
{
SetColLen();
SetColType();
} CHistoryDataOLEDB::~CHistoryDataOLEDB(void)
{
} void CHistoryDataOLEDB::SetColType(void)
{
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I2; col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_UI1;
col_type[] = DBTYPE_STR;
col_type[] = DBTYPE_I2; col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I4; col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I2;
col_type[] = DBTYPE_I4;
col_type[] = DBTYPE_I4; col_type[] = DBTYPE_STR;
} void CHistoryDataOLEDB::SetColLen(void)
{
col_len[] = sizeof(int);
col_len[] = sizeof(int);
col_len[] = sizeof(int);
col_len[] = sizeof(int);
col_len[] = sizeof(short); col_len[] = sizeof(short);
col_len[] = sizeof(short);
col_len[] = sizeof(char);
col_len[] = ;
col_len[] = sizeof(short); col_len[] = sizeof(short);
col_len[] = sizeof(short);
col_len[] = sizeof(short);
col_len[] = sizeof(int);
col_len[] = sizeof(int); col_len[] = sizeof(short);
col_len[] = sizeof(short);
col_len[] = sizeof(short);
col_len[] = sizeof(int);
col_len[] = sizeof(int); col_len[] = ;
} void CHistoryDataOLEDB::set_bindings()
{
set_bind(m_bindings[], , offsetof(HistoryData, Longitude_len), offsetof(HistoryData, Longitude_status), offsetof(HistoryData, Longitude_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Latitude_len), offsetof(HistoryData, Latitude_status), offsetof(HistoryData, Latitude_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Speed_len), offsetof(HistoryData, Speed_status), offsetof(HistoryData, Speed_value), col_len[], col_type[]); set_bind(m_bindings[], , offsetof(HistoryData, Direction_len), offsetof(HistoryData, Direction_status), offsetof(HistoryData, Direction_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Height_len), offsetof(HistoryData, Height_status), offsetof(HistoryData, Height_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Lock_len), offsetof(HistoryData, Lock_status), offsetof(HistoryData, Lock_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Gpstime_len), offsetof(HistoryData, Gpstime_status), offsetof(HistoryData, Gpstime_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, InStatus_len), offsetof(HistoryData, InStatus_status), offsetof(HistoryData, InStatus_value), col_len[], col_type[]); set_bind(m_bindings[], , offsetof(HistoryData, TmlStatus_len), offsetof(HistoryData, TmlStatus_status), offsetof(HistoryData, TmlStatus_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, WarnFlag_len), offsetof(HistoryData, WarnFlag_status), offsetof(HistoryData, WarnFlag_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Resver2_len), offsetof(HistoryData, Resver2_status), offsetof(HistoryData, Resver2_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Alldis_len), offsetof(HistoryData, Alldis_status), offsetof(HistoryData, Alldis_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Temperature_len), offsetof(HistoryData, Temperature_status), offsetof(HistoryData, Temperature_value), col_len[], col_type[]); set_bind(m_bindings[], , offsetof(HistoryData, Oil_len), offsetof(HistoryData, Oil_status), offsetof(HistoryData, Oil_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Smsid1_len), offsetof(HistoryData, Smaid1_status), offsetof(HistoryData, Smaid1_value), col_len[], col_type[]);
set_bind(m_bindings[], , offsetof(HistoryData, Smaid2_len), offsetof(HistoryData, Smaid2_status), offsetof(HistoryData, Smaid2_value), col_len[], col_type[]); set_bind(m_bindings[], , offsetof(HistoryData, AffixData_len), offsetof(HistoryData, AffixData_status), offsetof(HistoryData, AffixData_value), col_len[], col_type[]); } LPBYTE CHistoryDataOLEDB::FastQueryData(CStringW strSql,ULONG nColNum, int* nLen, int* nCount)
{
HRESULT hr = E_FAIL;
HistoryData rmd; //历史数据
HROW* rghRows = NULL;
LONG cRows = ; //一次读取10行
ULONG uRowsObtained = ; //实际读取的条数 IRowset *pIRowset = NULL;
IAccessor* pIAccessor = NULL;
HACCESSOR hAccessor = DB_NULL_HACCESSOR;
if (S_OK != (hr = CNativeClientOLEDB::FastQueryData(strSql, nColNum, &pIRowset, &pIAccessor, hAccessor))){
return NULL;
}
LPBYTE lpData = new BYTE[ * * ];
ZeroMemory(lpData, * * );
int nDataLen = ;
int nDataCount = ;
while (FALSE == FAILED(hr = pIRowset->GetNextRows( DB_NULL_HCHAPTER, , cRows, &uRowsObtained, &rghRows)))
{
int j = ;
if (cRows != uRowsObtained){
printf("cRows != uRowsObtained.\n");
} for (int i = ; i < uRowsObtained; ++i){
if (FAILED( hr = pIRowset->GetData(rghRows[i], hAccessor, &rmd )))
{
printf("获取数据失败 %d .\r\n", i);
break;
//std::cout << "获取数据失败." << std::endl;
} if (rmd.AffixData_status != || rmd.Alldis_status != || rmd.Direction_status != || rmd.Gpstime_status != ||
rmd.Height_status != || rmd.InStatus_status != || rmd.Latitude_status != || rmd.Latitude_status != || rmd.Lock_status != ||
rmd.Oil_status != || rmd.Speed_status != || rmd.Direction_status != ||
rmd.Resver2_status != || rmd.Smaid1_status != || rmd.Smaid2_status != || rmd.Temperature_status != ||
rmd.WarnFlag_status != ){
ASSERT();
break;
} HistoryGPSData gpsdata;
memset(&gpsdata, , sizeof(HistoryGPSData));
gpsdata.longitude = rmd.Longitude_value;
gpsdata.latitude = rmd.Latitude_value;
gpsdata.speed = rmd.Speed_value;
gpsdata.direction = rmd.Direction_value;
gpsdata.gpsHeight = rmd.Height_value;
gpsdata.byLock = rmd.Lock_value;
//TRACE("%s\n", rmd.Gpstime_value);
SYSTEMTIME sysGps;
sscanf(rmd.Gpstime_value, "%d-%d-%d %d:%d:%d", &sysGps.wYear, &sysGps.wMonth, &sysGps.wDay, &sysGps.wHour, &sysGps.wMinute, &sysGps.wSecond);
gpsdata.gpstm[] = sysGps.wYear - ;
gpsdata.gpstm[] = sysGps.wMonth;
gpsdata.gpstm[] = sysGps.wDay;
gpsdata.gpstm[] = sysGps.wHour;
gpsdata.gpstm[] = sysGps.wMinute;
gpsdata.gpstm[] = sysGps.wSecond;
int nInStatus = rmd.InStatus_value;
gpsdata.InStatus1 = nInStatus & 0xFF;
gpsdata.InStatus2 = (nInStatus >> ) & 0xFF;
int nTmlStatus = rmd.TmlStatus_value;
gpsdata.TmlStatus1 = nTmlStatus & 0xFF;
gpsdata.TmlStatus2 = (nTmlStatus >> ) & 0xFF;
int nWarnFlag = rmd.WarnFlag_value;
gpsdata.WarnFlag1 = nWarnFlag & 0xFF;
gpsdata.WarnFlag2 = (nWarnFlag >> ) & 0xFF;
int resver2 = rmd.Resver2_value;
gpsdata.extflag = resver2 &0xFF;
gpsdata.netid = (resver2 >> ) & 0xFF;
gpsdata.alldis = rmd.Alldis_value;
int nTemperatue = rmd.Temperature_value;
memcpy(gpsdata.temperture, &nTemperatue, );
gpsdata.oil = rmd.Oil_value;
gpsdata.cellid = rmd.Smaid2_value;
gpsdata.lacid = rmd.Smaid1_value;
CString strAffixData = rmd.AffixData_value; gpsdata.longitude = htonl(gpsdata.longitude);
gpsdata.latitude = htonl(gpsdata.latitude);
gpsdata.speed = htons(gpsdata.speed);
gpsdata.direction = htons(gpsdata.direction);
gpsdata.gpsHeight = htons(gpsdata.gpsHeight);
gpsdata.alldis = htonl(gpsdata.alldis);
gpsdata.oil = htons(gpsdata.oil);
gpsdata.cellid = htons(gpsdata.cellid);
gpsdata.lacid = htons(gpsdata.lacid); nDataCount++;
memcpy(lpData + nDataLen, &gpsdata, sizeof(HistoryGPSData));
nDataLen += sizeof(HistoryGPSData); //写入扩展数据
if(!strAffixData.IsEmpty())
{
BYTE bAffixData[] = {};
int nSrcLen = strAffixData.GetLength();
LPBYTE pSrcData = (LPBYTE)strAffixData.GetBuffer();
int nAffixLen = base64_decode(bAffixData, pSrcData, nSrcLen);
strAffixData.ReleaseBuffer();
if(nAffixLen > )
{
int nTmpLen = nAffixLen - ;
bAffixData[] = (nTmpLen >> ) & 0xFF;
bAffixData[] = nTmpLen & 0xFF;
memcpy(lpData + nDataLen, bAffixData, nAffixLen);
nDataLen += nAffixLen;
}
}
} if (uRowsObtained){
pIRowset->ReleaseRows(uRowsObtained, rghRows, NULL, NULL, NULL);
}
//释放
CoTaskMemFree(rghRows);
rghRows = NULL; if (hr == DB_S_ENDOFROWSET){
printf("数据已经全部读取完成共计:%d 条.", nDataCount);
break;
}
} //释放 IRowSet 和 IAccessor
ReleaseRowsetAndIAccessor(&pIRowset, &pIAccessor, hAccessor); if ( == nDataLen){
delete[] lpData;
lpData = NULL;
nDataCount = ;
nDataLen = ;
}
*nLen = nDataLen;
*nCount = nDataCount;
return lpData;
} BOOL CHistoryDataOLEDB::FastInsertData(const CStringW strTable, HistoryData* const pData, const int nDataNum)
{
if (NULL == pData || == nDataNum || strTable.IsEmpty()){
return TRUE;
} HRESULT hr = NOERROR;
IRowsetFastLoad * pIRowsetFastLoad = NULL;
IAccessor* pIAccessor = NULL;
HACCESSOR hAccessor = ;
ULONG nColNum = ;
if (S_OK != (hr = CNativeClientOLEDB::FastInsertData(strTable, nColNum, &pIRowsetFastLoad, &pIAccessor, hAccessor))){
return FALSE;
}
BOOL bRet = TRUE;
for (int i = ; i < nDataNum; i++){
if (FAILED(hr = pIRowsetFastLoad->InsertRow(hAccessor, &pData[i])))
{ DumpErrorInfo(pIRowsetFastLoad, IID_ISQLServerErrorInfo);
bRet = TRUE;
break;
}
}
//全部插入之后,提交一次
if (FAILED(hr = pIRowsetFastLoad->Commit(TRUE)))
{
DumpErrorInfo(pIRowsetFastLoad, IID_ISQLServerErrorInfo);
bRet = TRUE;
printf("Error on IRFL::Commit\n");
} ReleaseRowsetFastLoadAndIAccessor(&pIRowsetFastLoad, &pIAccessor, hAccessor);
if (bRet){
return FALSE;
} else {
return TRUE;
}
}

这个类继承于前面的类,用于对历史数据表的读取与插入. 以下我简单地说明一下:

1. 重写SetColLen() 来设置每列数据的长度.用于绑定

2. 重写SetColType() 来设置每列数据的类别.用于绑定

3. 重写 set_bindings() 来进行绑定.

4. FastQueryData 函数是快速查询数据的接口.

调用父类的FastQueryData来取得数据.利用GetNextRows从IRowset中取得数据.

5. 释放 IRowSet 和 IAccessor

6. 数据都是以数据流的方式查询返回和插入.

到此为止,基本OLEDB 操作算是结束了.

后续. 我写了个数据池来存储数据源的多个连接.其中也利用了信号量来保证了多线程同步的问题.

//CNativeClientOLEDBPool.h

 #pragma once

 #include <list>
using namespace std; template <class T>
class CNativeClientOLEDBPool
{
public:
CNativeClientOLEDBPool(void){
m_hSemaphore = NULL;
m_nMaxCount = ;
}
~CNativeClientOLEDBPool(void){
Clear();
}
//static CNativeClientOLEDBPool* Instance() { return &m_Instance; } //nCount连接数
HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG, int nCount = ){
HRESULT hr = S_OK;
ASSERT(nCount >= );
m_hSemaphore = ::CreateSemaphore(NULL, nCount, 0x7FFFFFFF, NULL); m_cs.Lock();
m_nMaxCount = nCount;
m_strDataSource = strDataSource;
m_strUserID = strUserID;
m_strPassWD = strPassWD;
m_strCataLOG = strCataLOG; for(int i=; i<m_nMaxCount; i++){
T* pConn = new T;
if (S_OK == (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))){
m_pConnList.push_back(pConn);
} else {
delete pConn;
break;
}
}
if(m_pConnList.size() != m_nMaxCount){
ASSERT();
}
m_cs.Unlock();
return hr;
} void Clear(){
if(m_hSemaphore)
{
::CloseHandle(m_hSemaphore);
m_hSemaphore = NULL;
} m_cs.Lock(); m_nMaxCount = ;
list<T*>::iterator it = m_pConnList.begin();
for(; it != m_pConnList.end(); it++)
{
T* pConn = *it;
if(pConn)
{
pConn->UnInit();
delete pConn;
}
}
m_pConnList.clear(); m_cs.Unlock();
} T* GetConnection(){
T* pConn = NULL;
if(::WaitForSingleObject(m_hSemaphore, INFINITE) != WAIT_OBJECT_0)
return pConn; m_cs.Lock();
if(!m_pConnList.empty())
{
pConn = m_pConnList.front();
m_pConnList.pop_front();
}
m_cs.Unlock(); if(pConn == NULL)
{
//create new database connection
pConn = new T();
HRESULT hr = NOERROR;
if(S_OK != (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))) {
delete pConn;
pConn = NULL;
}
}
return pConn;
}
void FreeConnection(T* pConn){
ASSERT(pConn != NULL); BOOL bSemaphore = FALSE; m_cs.Lock();
if(m_pConnList.size() >= m_nMaxCount)
{
pConn->UnInit();
delete pConn;
}
else
{
m_pConnList.push_back(pConn);
bSemaphore = TRUE;
}
m_cs.Unlock(); if(bSemaphore)
{
::ReleaseSemaphore(m_hSemaphore, , NULL);
}
} public:
BOOL ReOpenConnection(T* pConn){
return FALSE;
} BOOL VerifyConnection(T* pConn){
return TRUE;
} protected:
int m_nMaxCount;
CStringW m_strDataSource;
CStringW m_strUserID;
CStringW m_strPassWD;
CStringW m_strCataLOG;
CCriticalSection m_cs;
list<T*> m_pConnList; HANDLE m_hSemaphore;
//static CNativeClientOLEDBPool m_Instance;
}; #pragma once #include <list>
using namespace std; template <class T>
class CNativeClientOLEDBPool
{
public:
CNativeClientOLEDBPool(void){
m_hSemaphore = NULL;
m_nMaxCount = ;
}
~CNativeClientOLEDBPool(void){
Clear();
}
//static CNativeClientOLEDBPool* Instance() { return &m_Instance; } //nCount连接数
HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG, int nCount = ){
HRESULT hr = S_OK;
ASSERT(nCount >= );
m_hSemaphore = ::CreateSemaphore(NULL, nCount, 0x7FFFFFFF, NULL); m_cs.Lock();
m_nMaxCount = nCount;
m_strDataSource = strDataSource;
m_strUserID = strUserID;
m_strPassWD = strPassWD;
m_strCataLOG = strCataLOG; for(int i=; i<m_nMaxCount; i++){
T* pConn = new T;
if (S_OK == (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))){
m_pConnList.push_back(pConn);
} else {
delete pConn;
break;
}
}
if(m_pConnList.size() != m_nMaxCount){
ASSERT();
}
m_cs.Unlock();
return hr;
} void Clear(){
if(m_hSemaphore)
{
::CloseHandle(m_hSemaphore);
m_hSemaphore = NULL;
} m_cs.Lock(); m_nMaxCount = ;
list<T*>::iterator it = m_pConnList.begin();
for(; it != m_pConnList.end(); it++)
{
T* pConn = *it;
if(pConn)
{
pConn->UnInit();
delete pConn;
}
}
m_pConnList.clear(); m_cs.Unlock();
} T* GetConnection(){
T* pConn = NULL;
if(::WaitForSingleObject(m_hSemaphore, INFINITE) != WAIT_OBJECT_0)
return pConn; m_cs.Lock();
if(!m_pConnList.empty())
{
pConn = m_pConnList.front();
m_pConnList.pop_front();
}
m_cs.Unlock(); if(pConn == NULL)
{
//create new database connection
pConn = new T();
HRESULT hr = NOERROR;
if(S_OK != (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))) {
delete pConn;
pConn = NULL;
}
}
return pConn;
}
void FreeConnection(T* pConn){
ASSERT(pConn != NULL); BOOL bSemaphore = FALSE; m_cs.Lock();
if(m_pConnList.size() >= m_nMaxCount)
{
pConn->UnInit();
delete pConn;
}
else
{
m_pConnList.push_back(pConn);
bSemaphore = TRUE;
}
m_cs.Unlock(); if(bSemaphore)
{
::ReleaseSemaphore(m_hSemaphore, , NULL);
}
} public:
BOOL ReOpenConnection(T* pConn){
return FALSE;
} BOOL VerifyConnection(T* pConn){
return TRUE;
} protected:
int m_nMaxCount;
CStringW m_strDataSource;
CStringW m_strUserID;
CStringW m_strPassWD;
CStringW m_strCataLOG;
CCriticalSection m_cs;
list<T*> m_pConnList; HANDLE m_hSemaphore;
//static CNativeClientOLEDBPool m_Instance;
};

CNativeClientOLEDBPool.cpp 为空

查询数据的时候,就把会话创建出来,执行语句之后(可多次),释放会话.

pDB->CreateSessionAndCommand();
DWORD dwTick = ::GetTickCount();
m_lpData = pDB->FastQueryData(strSql, 17, &m_nDataLen, &m_nCount);
DWORD dwTick2 = ::GetTickCount();
pDB->ReleaseSessionAndCommand();

实测: 确实比ADO的要快三倍以上.虽然比ADO访问上复杂一点.但你要懂了,也觉得很简单.

以上的封装只是针对某张表需要进行高速访问和插入来的.

查询的话.每张表都要写相对应的数据绑定. 当然你也可以在外层调用,自行绑定.哈哈~

后续:

后来我也进行了ODBC API的数据访问测试,效率跟OLEDB相差不多.

需要代码的话,我也可以贴出来.

目前微软已经不对OLEDB进行艮新了.但7年之内还是保持支持.

后续都会采用ODBC来访问数据库.

参考资料:

微软官方MSDN:https://msdn.microsoft.com/zh-cn/library/ms131687(v=sql.120).aspx

frank_liuxing博客:http://blog.csdn.net/frank_liuxing/article/details/43231233

我淋着雨博客:http://www.cnblogs.com/smartstone/archive/2006/04/23/383002.html

感谢这两位大牛.

利用Native Client OLEDB 11 高效率地对SQL SERVER 进行查询和插入操作的更多相关文章

  1. Part 11 string functions in sql server

    Built in string functions in sql server 2008 LEFT, RIGHT, CHARINDEX and SUBSTRING functions in sql s ...

  2. 2018年11月16日SQL Server实验内容(触发器实验)

    --注意:先把studentmanager数据库中的所有表用select into命令复制一份, --然后用复制后新表完成下面的实验,同时,对每个触发器都要进行验证. select *into dep ...

  3. 利用Ring Buffer在SQL Server 2008中进行连接故障排除

    原文:利用Ring Buffer在SQL Server 2008中进行连接故障排除 出自:http://blogs.msdn.com/b/apgcdsd/archive/2011/11/21/ring ...

  4. SQL SERVER中的OLEDB等待事件

    OLEDB等待事件介绍 OLEDB等待类型是SQL SERVER 数据库中最常见的几种等待类型之一.它意味着某个会话(SPID)通过SQL Server Native Client OLEDB Pro ...

  5. SQL Server调优系列玩转篇(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  6. 利用PowerDesigner绘制PDM生成SQL Server数据库

    PowerDesigner是个很强大的建模工具,可以利用它绘制各种图形,本文利用该工具绘制PDM,进而生成SQL Server数据库. 比如绘制一个简单的学生选课.教师授课管理系统的PDM: pk表示 ...

  7. SQL Server 调优系列玩转篇一(如何利用查询提示(Hint)引导语句运行)

    前言 前面几篇我们分析了关于SQL Server关于性能调优的一系列内容,我把它分为两个模块. 第一个模块注重基础内容的掌握,共分7篇文章完成,内容涵盖一系列基础运算算法,详细分析了如何查看执行计划. ...

  8. navicat 连接sqlserver提示要安装 sql server native client

    navicat 连接sqlserver提示要安装 sql server native client 解决方法:其实navicat自带sqlncli_x64.msi,就在安装目录下,安装后问题解决!

  9. 解决:安装SQL Server 2008 Native Client遇到错误(在Navicat premium新建sqlserver连接时 需要):An error occurred during ...HRESULT: 0x80070422(注意尾部的错误号)

    解决:安装SQL Server 2008 Native Client遇到错误(在Navicat premium新建sqlserver连接时 需要):An error occurred during . ...

随机推荐

  1. .gitignore 使用中注意的问题

    在git中如果想忽略掉某个文件,不让这个文件提交到版本库中,可以使用修改 .gitignore 文件的方法.这个文件每一行保存了一个匹配的规则例如: # 此为注释 – 将被 Git 忽略 *.a    ...

  2. zookeeper入门学习

    1.基本概念 ZooKeeper是一个分布式的,开放源码的分布式应用程序协调服务,是Google的Chubby一个开源的实现,是Hadoop和Hbase的重要组件.它是一个为分布式应用提供一致性服务的 ...

  3. Dynamics AX Hostory

    现在谈起Dynamics AX,在微软Dynamics系列产品当中,作为最受瞩目和最有前景的Dynamics套装产品线,很多人也许只知道它曾经由于资本市场的上市和并购,前后经历了三个“东家”.对于它长 ...

  4. 在树莓派2代B型/3代 上安装Fedora23 - Installing Fedora 23 on Raspberry Pi 2 model B or Raspberry Pi 3

    本文主要用于记录安装过程,以便日后查阅回顾. 之前在自己的树莓派上运行的一直是通过NOOB安装的Raspbian,但是本人平时更喜欢用Fedora作为开发和使用环境,而且Raspbian上的软件包通常 ...

  5. 二模14day2解题报告

    T1.砍树(cuttree) 给出n棵树,要锯下m米木材,现在有一个高度h,h以上所有木头都砍下来,求满足m米的最小h 很简单的二分答案判断可行性. T2.快速求和(quicksum) 给出数字串s, ...

  6. IE11错误:Exception in window.onload: An error has occuredJSPlugin.3005 解决方案

    问题:新安装的IE11无法使用F12开发者工具,DOC资源管理器提示错误“Exception in window.onload: An error has occuredJSPlugin.3005”. ...

  7. isMemberOfClass和isKindOfClass的区别

    1.isMemberOfClass:作用:用于判断一个对象是否属于当前这个类   Person *rose = [[Person alloc] init];          if ([rose is ...

  8. 学校系统快速js代码

    var select_arr=document.getElementById("iframeautoheight").contentWindow.document.getEleme ...

  9. WPF的二维绘图(二)——几何图形Geometry

    在WPF的DrawingContext对象中,提供了基本的绘制椭圆和矩形的API:DrawEllipse和DrawRectangle.但是,这些是远远不够用的,我们在日常应用中,更多的是使用DrawG ...

  10. Linux和windows之间通过scp复制文件

    Windows是不支持ssh协议的 需要安装WinSSHD 安装以及设置过程如下: BvSshServer(原名winsshd)官方下载页在这里:https://www.bitvise.com/dow ...