利用Native Client OLEDB 11 高效率地对SQL SERVER 进行查询和插入操作

前言:

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

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

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

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

//NativeClientOLEDB.h 

  1 #pragma once
  2 
  3 #include <oledb.h>
  4 #include <oledberr.h>
  5 #include <stdio.h>
  6 #include <stddef.h>   // for offsetof
  7 
  8 #include <msdaguid.h>
  9 #include <msdasql.h>
 10 #include <msdasc.h>
 11 #include <sqlncli.h>
 12 #include <string>
 13 //#include "C:Program FilesMicrosoft SQL Server110SDKIncludesqlncli.h"
 14 
 15 #ifndef _AUTHOR_NAME
 16 #define _AUTHOR_NAME        "沈春钟"
 17 #define _CREATE_DATE        "2016-05-18"
 18 #define _LIBRARY_TITLE        "NativeClientOLEDB"
 19 #define _LIBRARY_DESC        "对NaTiveClientOLEDB的封装"
 20 #define _MAINTAIN_CONTACT    "SamRichard@live.cn"
 21 #define _MAX_COL_NUM        100
 22 #endif
 23 
 24 #pragma comment(lib, "sqlncli11.lib")
 25 
 26 
 27 // @type UWORD    | 2 byte unsigned integer.
 28 typedef unsigned short UWORD;
 29 
 30 // @type SDWORD   | 4 byte signed integer.
 31 typedef signed long SDWORD;
 32 
 33 using namespace std;
 34 
 35 //委托表数据结构体
 36 #pragma pack(push, 1)
 37 class Data
 38 {
 39     //SDWORD SOID_len;   // Length of data (not space allocated).
 40     //DWORD SOID_status;   // Status of column.
 41     //int SOID_value;
 42 };
 43 #pragma pack(pop)
 44 
 45 //// How to lay out each column in memory.
 46 //struct COLUMNDATA {
 47 //    SDWORD idLen;   // Length of data (not space allocated).
 48 //    DWORD idStatus;   // Status of column.
 49 //    int id;   // Store data here as a variant.
 50 //    SDWORD dateLen;
 51 //    DWORD dateStatus;
 52 //    char date[21];
 53 //};
 54 
 55 class CNativeClientOLEDB
 56 {
 57 public:
 58     CNativeClientOLEDB(void);
 59     ~CNativeClientOLEDB(void);
 60 
 61 public:
 62     //初始化连接
 63     HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG);
 64     //不建议用此方式初始化
 65     HRESULT Init(CStringW strConnectionString);
 66     //释放连接
 67     void UnInit();
 68 
 69 protected:
 70     //函数申明
 71     virtual void set_bindings();
 72     //设置每列数据列的类型
 73     virtual void SetColType(void);
 74     //设置每列数据列的长度
 75     virtual void SetColLen(void);
 76 
 77     //bind one by one
 78     void set_bind(DBBINDING &binding, int col, DBBYTEOFFSET len_offset, DBBYTEOFFSET status_offset, DBBYTEOFFSET value_offset, DBLENGTH len, DBTYPE type);
 79 
 80     void DumpErrorInfo(IUnknown* pObjectWithError, REFIID IID_InterfaceWithError);
 81 
 82     //HRESULT FastInsertData();
 83     //快速查询数据
 84     HRESULT FastQueryData(CStringW strSql,ULONG& nColNum, IRowset** pIRowset,IAccessor** pIAccessor, HACCESSOR& hAccessor);
 85     //释放RowSet和IAccessor
 86     HRESULT ReleaseRowsetAndIAccessor(IRowset** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor);
 87     //快速插入数据
 88     HRESULT FastInsertData(CStringW strTable, ULONG& nColNum, IRowsetFastLoad** pIRowsetFastLoad, IAccessor** pIAccessor, HACCESSOR& hAccessor);
 89     //释放RowsetFast和IAccessor
 90     HRESULT ReleaseRowsetFastLoadAndIAccessor(IRowsetFastLoad** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor);
 91 
 92 private:
 93 
 94     // Given an ICommand pointer, properties, and query, a rowsetpointer is returned.
 95     HRESULT DBInitAndConnect(DBPROPSET* rgPropertySets, ULONG ulcPropCount, CLSID clsidProv);
 96 
 97     // Use to set properties and execute a given query.
 98     HRESULT ExecuteQuery(IDBCreateCommand* pIDBCreateCommand,
 99         WCHAR* pwszQuery,
100         DBPROPSET* rgPropertySets,
101         ULONG ulcPropCount,
102         LONG* pcRowsAffected,
103         IRowset** ppIRowset,
104         BOOL fSuccessOnly = TRUE);
105 
106     // Use to set up options for call to IDBInitialize::Initialize.
107     void SetupOption(DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp);
108 
109     // Sets fastload property on/off for session.
110     HRESULT SetFastLoadProperty(BOOL fSet);
111 
112 public:
113     //创建会话和命令
114     HRESULT CreateSessionAndCommand();
115     //释放会话和命令
116     HRESULT ReleaseSessionAndCommand();
117     //设置模式和创建会话
118     HRESULT SetPropertiesAndCreateSessionAndIOpenRowset(BOOL bFast = TRUE);
119     //释放会话
120     HRESULT ReleaseSessionIOpenRowset();
121 
122 private:
123     //初始化层
124     IMalloc* m_pIMalloc;
125     IDataInitialize* m_pIDataInitialize;
126     IDBInitialize* m_pIDBInitialize;
127     // OLE initialized?
128     BOOL m_bInitialized;
129     //回话和命令层
130     IDBCreateSession* m_pIDBSession;
131     IOpenRowset* m_pIOpenRowset;
132     ICommand* m_pICommand;
133     IDBCreateCommand* m_pIDBCreateCommand;
134     ICommandText* m_pICommandText;
135     DBID TableID;
136 
137 protected:
138     //binding数组
139     DBBINDING m_bindings[_MAX_COL_NUM];
140 
141     //委托表每列的数据类型
142     DBTYPEENUM col_type[_MAX_COL_NUM];
143 
144     //委托表每列的数据长度
145     DBBYTEOFFSET col_len[_MAX_COL_NUM];
146 };
147 
148  
View Code

//NativeClientOLEDB.cpp

  1 #include "StdAfx.h"
  2 #include "NativeClientOLEDB.h"
  3 #include <time.h>
  4 #include <Base64.h>
  5 
  6 #define COUNT  10000
  7 #define ROW_SIZE  1000
  8 
  9 #define COLUMN_ALIGNVAL 8
 10 #define ROUND_UP(Size, Amount)(((DWORD)(Size) + ((Amount)-1)) & ~((Amount)-1))
 11 
 12 const UWORD g_cOPTION = 4;
 13 const UWORD MAXPROPERTIES = 5;
 14 const ULONG DEFAULT_CBMAXLENGTH = 20;
 15 
 16 
 17 CNativeClientOLEDB::CNativeClientOLEDB(void)
 18 {
 19     m_pIMalloc = NULL;
 20     m_pIDBInitialize = NULL;
 21     m_bInitialized = FALSE;
 22     m_pIDBSession = NULL;
 23     m_pIOpenRowset  = NULL;
 24     m_pICommand = NULL;
 25     m_pIDBCreateCommand = NULL;
 26     m_pICommandText = NULL;
 27     TableID.uName.pwszName = NULL;
 28     m_pIDataInitialize = NULL;
 29     SetColType();
 30     SetColLen();
 31 }
 32 
 33 CNativeClientOLEDB::~CNativeClientOLEDB(void)
 34 {
 35     ReleaseSessionAndCommand();
 36     UnInit();
 37 }
 38 
 39 HRESULT CNativeClientOLEDB::Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG)
 40 {
 41     HRESULT hr = NOERROR;
 42     // One property set for initializing.
 43     DBPROPSET rgPropertySets[1];
 44     // Properties within above property set.
 45     DBPROP rgDBProperties[g_cOPTION];
 46     do 
 47     {
 48         // Basic initialization.
 49         if (FAILED(CoInitialize(NULL)))
 50             break;
 51         else
 52             m_bInitialized = TRUE;
 53 
 54         hr = CoGetMalloc(MEMCTX_TASK, &m_pIMalloc);
 55         if ((!m_pIMalloc) || FAILED(hr))
 56             break;
 57 
 58         // Set up property set for call to IDBInitialize in CreateSessionCommand.
 59         rgPropertySets[0].rgProperties = rgDBProperties;
 60         rgPropertySets[0].cProperties = g_cOPTION;
 61         rgPropertySets[0].guidPropertySet = DBPROPSET_DBINIT;
 62 
 63         SetupOption(DBPROP_INIT_DATASOURCE, (WCHAR *)(LPCWSTR)strDataSource, &rgDBProperties[0]);
 64         SetupOption(DBPROP_INIT_CATALOG, (WCHAR *)(LPCWSTR)strCataLOG, &rgDBProperties[1]);
 65         SetupOption(DBPROP_AUTH_USERID, (WCHAR *)(LPCWSTR)strUserID, &rgDBProperties[2]);
 66         SetupOption(DBPROP_AUTH_PASSWORD, (WCHAR *)(LPCWSTR)strPassWD, &rgDBProperties[3]);
 67 
 68         //if (S_OK != (hr = DBInitAndConnect(rgPropertySets, 1, SQLNCLI_CLSID)))
 69         if (S_OK != (hr = DBInitAndConnect(rgPropertySets, 1, CLSID_SQLNCLI11)))
 70             break;
 71         return S_OK;
 72     } while (0);
 73 
 74     return hr;
 75 }
 76 
 77 HRESULT CNativeClientOLEDB::Init(CStringW strConnectionString)
 78 {
 79     HRESULT hr  = S_OK;
 80     do 
 81     {
 82 
 83         if (FAILED(CoInitialize(NULL)))
 84             break;
 85         else
 86             m_bInitialized = TRUE;
 87 
 88         hr = CoCreateInstance(
 89             CLSID_MSDAINITIALIZE,
 90             NULL,
 91             CLSCTX_INPROC_SERVER,
 92             IID_IDataInitialize,
 93             reinterpret_cast<LPVOID *>(&m_pIDataInitialize));
 94         if (!SUCCEEDED(hr))
 95             break;
 96 
 97 
 98         hr = m_pIDataInitialize->GetDataSource(
 99             NULL,
100             CLSCTX_INPROC_SERVER,
101             strConnectionString,            
102             IID_IDBInitialize,
103             reinterpret_cast<IUnknown **>(&m_pIDBInitialize));
104 
105         if (!SUCCEEDED(hr))
106             break;
107 
108         if (!SUCCEEDED(hr = m_pIDBInitialize->Initialize())) {
109             printf("Call to initialize failed.
");
110             break;
111         }
112 
113         return S_OK;
114 
115     } while (0);
116 
117     UnInit();
118     return hr;
119 }
120 
121 void CNativeClientOLEDB::UnInit()
122 {
123     HRESULT hr = NOERROR;
124 
125     //ReleaseSessionAndCommand();
126     //ReleaseSessionIOpenRowset();
127 
128     if (m_pIMalloc){
129         m_pIMalloc->Release();
130         m_pIMalloc = NULL;
131     }
132 
133     if (m_pIDBInitialize) {
134         hr = m_pIDBInitialize->Uninitialize();
135         m_pIDBInitialize = NULL;
136         if (FAILED(hr))
137             printf("Uninitialize failed
");
138     }
139 
140     if (m_bInitialized){
141         CoUninitialize();
142         m_bInitialized = FALSE;
143     }
144 
145     if (SUCCEEDED(hr))
146         printf("Test completed successfully.

");
147     else
148         printf("Test failed.

");
149 
150 }
151 
152 void CNativeClientOLEDB::SetColType(void)
153 {
154 
155 }
156 
157 void CNativeClientOLEDB::SetColLen(void)
158 {
159     
160 }
161 
162 void CNativeClientOLEDB::set_bindings()
163 {
164 
165 }
166 
167 void CNativeClientOLEDB::set_bind(DBBINDING &binding, int col, DBBYTEOFFSET len_offset, DBBYTEOFFSET status_offset, DBBYTEOFFSET value_offset, DBLENGTH len, DBTYPE type)
168 {
169     binding.dwPart = DBPART_VALUE | DBPART_LENGTH | DBPART_STATUS;
170     binding.iOrdinal = col;
171     binding.pTypeInfo = NULL;
172     binding.obValue = value_offset;
173     binding.obLength = len_offset;
174     binding.obStatus = status_offset;
175     binding.cbMaxLen = len;   // Size of varchar column.
176     binding.pTypeInfo = NULL;
177     binding.pObject = NULL;
178     binding.pBindExt = NULL;
179     binding.dwFlags = 0;
180     binding.eParamIO = DBPARAMIO_NOTPARAM;
181     binding.dwMemOwner = DBMEMOWNER_CLIENTOWNED;
182     binding.bPrecision = 0;
183     binding.bScale = 0;
184     binding.wType = type;
185 }
186 
187 HRESULT CNativeClientOLEDB::DBInitAndConnect(DBPROPSET* rgPropertySets, ULONG ulcPropCount, CLSID clsidProv)
188 {
189     HRESULT hr = NOERROR;
190     IDBProperties* pIDBProperties = NULL;
191     UWORD i = 0, j = 0;   // indexes.
192 
193     if (ulcPropCount && !rgPropertySets) {
194         hr = E_INVALIDARG;
195         return hr;
196     }
197 
198     if (S_OK != (hr = CoCreateInstance(clsidProv,
199         NULL, CLSCTX_INPROC_SERVER,
200         IID_IDBInitialize,
201         (void **)&m_pIDBInitialize))){
202             goto CLEANUP;
203     }
204 
205     if (S_OK != (hr = m_pIDBInitialize->QueryInterface(IID_IDBProperties,
206         (void **)&pIDBProperties)))
207         goto CLEANUP;
208 
209     if (S_OK != (hr = pIDBProperties->SetProperties(ulcPropCount, rgPropertySets))){
210         goto CLEANUP;
211     }
212     
213     if (S_OK != (hr = m_pIDBInitialize->Initialize())) {
214 
215         printf("Call to initialize failed.
");
216         goto CLEANUP;
217     }
218 
219 CLEANUP:
220     if (pIDBProperties)
221         pIDBProperties->Release();
222 
223     for (i = 0; i < ulcPropCount; i++)
224         for (j = 0; j < rgPropertySets[i].cProperties; j++)
225             VariantClear(&(rgPropertySets[i].rgProperties[j]).vValue);
226     return hr;
227 }
228 
229 void CNativeClientOLEDB::DumpErrorInfo(IUnknown* pObjectWithError, REFIID IID_InterfaceWithError)
230 {
231     // Interfaces used in the example.
232     IErrorInfo*             pIErrorInfoAll = NULL;
233     IErrorInfo*             pIErrorInfoRecord = NULL;
234     IErrorRecords*          pIErrorRecords = NULL;
235     ISupportErrorInfo*      pISupportErrorInfo = NULL;
236     ISQLErrorInfo*          pISQLErrorInfo = NULL;
237     ISQLServerErrorInfo*    pISQLServerErrorInfo = NULL;
238 
239     // Number of error records.
240     ULONG                   nRecs;
241     ULONG                   nRec;
242 
243     // Basic error information from GetBasicErrorInfo.
244     ERRORINFO               errorinfo;
245 
246     // IErrorInfo values.
247     BSTR                    bstrDescription;
248     BSTR                    bstrSource;
249 
250     // ISQLErrorInfo parameters.
251     BSTR                    bstrSQLSTATE;
252     LONG                    lNativeError;
253 
254     // ISQLServerErrorInfo parameter pointers.
255     SSERRORINFO*            pSSErrorInfo = NULL;
256     OLECHAR*                pSSErrorStrings = NULL;
257 
258     // Hard-code an American English locale for the example.
259     DWORD                   MYLOCALEID = 0x0409;
260 
261     // Only ask for error information if the interface supports
262     // it.
263     if (FAILED(pObjectWithError->QueryInterface(IID_ISupportErrorInfo,
264         (void**)&pISupportErrorInfo)))
265     {
266         wprintf_s(L"SupportErrorErrorInfo interface not supported");
267         return;
268     }
269     if (FAILED(pISupportErrorInfo->
270         InterfaceSupportsErrorInfo(IID_InterfaceWithError)))
271     {
272         wprintf_s(L"InterfaceWithError interface not supported");
273         return;
274     }
275 
276     // Do not test the return of GetErrorInfo. It can succeed and return
277     // a NULL pointer in pIErrorInfoAll. Simply test the pointer.
278     GetErrorInfo(0, &pIErrorInfoAll);
279 
280     if (pIErrorInfoAll != NULL)
281     {
282         // Test to see if it's a valid OLE DB IErrorInfo interface 
283         // exposing a list of records.
284         if (SUCCEEDED(pIErrorInfoAll->QueryInterface(IID_IErrorRecords,
285             (void**)&pIErrorRecords)))
286         {
287             pIErrorRecords->GetRecordCount(&nRecs);
288 
289             // Within each record, retrieve information from each
290             // of the defined interfaces.
291             for (nRec = 0; nRec < nRecs; nRec++)
292             {
293                 // From IErrorRecords, get the HRESULT and a reference
294                 // to the ISQLErrorInfo interface.
295                 pIErrorRecords->GetBasicErrorInfo(nRec, &errorinfo);
296                 pIErrorRecords->GetCustomErrorObject(nRec,
297                     IID_ISQLErrorInfo, (IUnknown**)&pISQLErrorInfo);
298 
299                 // Display the HRESULT, then use the ISQLErrorInfo.
300                 wprintf_s(L"HRESULT:	%#X
", errorinfo.hrError);
301 
302                 if (pISQLErrorInfo != NULL)
303                 {
304                     pISQLErrorInfo->GetSQLInfo(&bstrSQLSTATE,
305                         &lNativeError);
306 
307                     // Display the SQLSTATE and native error values.
308                     wprintf_s(L"SQLSTATE:	%s
Native Error:	%ld
",
309                         bstrSQLSTATE, lNativeError);
310 
311                     // SysFree BSTR references.
312                     SysFreeString(bstrSQLSTATE);
313 
314                     // Get the ISQLServerErrorInfo interface from
315                     // ISQLErrorInfo before releasing the reference.
316                     pISQLErrorInfo->QueryInterface(
317                         IID_ISQLServerErrorInfo,
318                         (void**)&pISQLServerErrorInfo);
319 
320                     pISQLErrorInfo->Release();
321                 }
322 
323                 // Test to ensure the reference is valid, then
324                 // get error information from ISQLServerErrorInfo.
325                 if (pISQLServerErrorInfo != NULL)
326                 {
327                     pISQLServerErrorInfo->GetErrorInfo(&pSSErrorInfo,
328                         &pSSErrorStrings);
329 
330                     // ISQLServerErrorInfo::GetErrorInfo succeeds
331                     // even when it has nothing to return. Test the
332                     // pointers before using.
333                     if (pSSErrorInfo)
334                     {
335                         // Display the state and severity from the
336                         // returned information. The error message comes
337                         // from IErrorInfo::GetDescription.
338                         wprintf_s(L"Error state:	%d
Severity:	%d
",
339                             pSSErrorInfo->bState,
340                             pSSErrorInfo->bClass);
341 
342                         // IMalloc::Free needed to release references
343                         // on returned values. For the example, assume
344                         // the g_pIMalloc pointer is valid.
345                         m_pIMalloc->Free(pSSErrorStrings);
346                         m_pIMalloc->Free(pSSErrorInfo);
347                     }
348 
349                     pISQLServerErrorInfo->Release();
350                 }
351 
352                 if (SUCCEEDED(pIErrorRecords->GetErrorInfo(nRec,
353                     MYLOCALEID, &pIErrorInfoRecord)))
354                 {
355                     // Get the source and description (error message)
356                     // from the record's IErrorInfo.
357                     pIErrorInfoRecord->GetSource(&bstrSource);
358                     pIErrorInfoRecord->GetDescription(&bstrDescription);
359 
360                     if (bstrSource != NULL)
361                     {
362                         wprintf_s(L"Source:		%s
", bstrSource);
363                         SysFreeString(bstrSource);
364                     }
365                     if (bstrDescription != NULL)
366                     {
367                         wprintf_s(L"Error message:	%s
",
368                             bstrDescription);
369                         SysFreeString(bstrDescription);
370                     }
371 
372                     pIErrorInfoRecord->Release();
373                 }
374             }
375 
376             pIErrorRecords->Release();
377         }
378         else
379         {
380             // IErrorInfo is valid; get the source and
381             // description to see what it is.
382             pIErrorInfoAll->GetSource(&bstrSource);
383             pIErrorInfoAll->GetDescription(&bstrDescription);
384 
385             if (bstrSource != NULL)
386             {
387                 wprintf_s(L"Source:		%s
", bstrSource);
388                 SysFreeString(bstrSource);
389             }
390             if (bstrDescription != NULL)
391             {
392                 wprintf_s(L"Error message:	%s
", bstrDescription);
393                 SysFreeString(bstrDescription);
394             }
395         }
396 
397         pIErrorInfoAll->Release();
398     }
399     else
400     {
401         wprintf_s(L"GetErrorInfo failed.");
402     }
403 
404     pISupportErrorInfo->Release();
405 
406     return;
407 }
408 
409 void CNativeClientOLEDB::SetupOption(DBPROPID PropID, WCHAR *wszVal, DBPROP * pDBProp)
410 {
411     pDBProp->dwPropertyID = PropID;
412     pDBProp->dwOptions = DBPROPOPTIONS_REQUIRED;
413     pDBProp->colid = DB_NULLID;
414     pDBProp->vValue.vt = VT_BSTR;
415     pDBProp->vValue.bstrVal = SysAllocStringLen(wszVal, wcslen(wszVal));
416 }
417 
418 HRESULT CNativeClientOLEDB::SetFastLoadProperty(BOOL fSet)
419 {
420     HRESULT hr = S_OK;
421     IDBProperties* pIDBProps = NULL;
422     DBPROP rgProps[1];
423     DBPROPSET PropSet;
424 
425     VariantInit(&rgProps[0].vValue);
426 
427     rgProps[0].dwOptions = DBPROPOPTIONS_REQUIRED;
428     rgProps[0].colid = DB_NULLID;
429     rgProps[0].vValue.vt = VT_BOOL;
430     rgProps[0].dwPropertyID = SSPROP_ENABLEFASTLOAD;
431 
432     if (fSet == TRUE)
433         rgProps[0].vValue.boolVal = VARIANT_TRUE;
434     else
435         rgProps[0].vValue.boolVal = VARIANT_FALSE;
436 
437     PropSet.rgProperties = rgProps;
438     PropSet.cProperties = 1;
439     PropSet.guidPropertySet = DBPROPSET_SQLSERVERDATASOURCE;
440 
441     if (SUCCEEDED(hr = m_pIDBInitialize->QueryInterface(IID_IDBProperties, (LPVOID *)&pIDBProps)))
442         hr = pIDBProps->SetProperties(1, &PropSet);
443 
444     VariantClear(&rgProps[0].vValue);
445 
446     if (pIDBProps)
447         pIDBProps->Release();
448 
449     return hr;
450 }
451 
452 HRESULT CNativeClientOLEDB::FastQueryData(CStringW strSql,ULONG& nColNum,IRowset** pIRowset,IAccessor** pIAccessor, HACCESSOR& hAccessor)
453 {
454 
455     HRESULT hr = E_FAIL;
456     if (NULL != *pIRowset || NULL != *pIAccessor || strSql.IsEmpty() || NULL == m_pICommandText || NULL == m_pICommand || nColNum <= 0){
457         return hr;
458     }
459     do 
460     {
461         if (FAILED(hr = m_pICommandText->SetCommandText(DBGUID_DBSQL, strSql))){
462             break;
463         }
464 
465         LONG lAffected;
466         if (FAILED(hr = m_pICommand->Execute(NULL, IID_IRowset, NULL, &lAffected, (IUnknown **)pIRowset))){
467             break;
468         }
469 
470         if (FAILED(hr = (*pIRowset)->QueryInterface(IID_IAccessor, (void **)pIAccessor))){
471             break;
472         }
473 
474         set_bindings();
475 
476         DBBINDSTATUS dbs[_MAX_COL_NUM] = { 0 };
477         if (FAILED(hr = (*pIAccessor)->CreateAccessor(DBACCESSOR_ROWDATA, (DBCOUNTITEM)nColNum, m_bindings, sizeof(Data),&hAccessor, dbs))){
478             //dbs是绑定状态
479             break;
480         }
481         
482         return S_OK;
483     } while (0);
484     
485     ReleaseRowsetAndIAccessor(pIRowset, pIAccessor, hAccessor);
486 }
487 
488 
489 HRESULT CNativeClientOLEDB::FastInsertData(CStringW strTable, ULONG& nColNum, IRowsetFastLoad** pIRowsetFastLoad, IAccessor** pIAccessor, HACCESSOR& hAccessor)
490 {
491     HRESULT hr = E_FAIL;
492     TableID.uName.pwszName = NULL;
493     TableID.eKind = DBKIND_NAME;
494     TableID.uName.pwszName = new WCHAR[strTable.GetLength() + 2];
495     wcsncpy_s(TableID.uName.pwszName, strTable.GetLength() + 2, strTable, strTable.GetLength() + 1);
496     TableID.uName.pwszName[strTable.GetLength() + 1] = (WCHAR)NULL;
497 
498     do 
499     {
500         // Get IRowsetFastLoad initialized to use the test table.
501         if (FAILED(hr =    m_pIOpenRowset->OpenRowset(NULL, &TableID, NULL, IID_IRowsetFastLoad, 0, NULL, (LPUNKNOWN *)pIRowsetFastLoad))){
502             break;
503         }
504 
505         set_bindings();
506         DBBINDSTATUS bds[_MAX_COL_NUM] = { 0 };
507         if (FAILED(hr =    (*pIRowsetFastLoad)->QueryInterface(IID_IAccessor, (void **)pIAccessor))){
508             break;
509         }
510 
511         if (FAILED(hr = (*pIAccessor)->CreateAccessor(DBACCESSOR_ROWDATA, (DBCOUNTITEM)nColNum, m_bindings, (ROUND_UP(sizeof(Data), COLUMN_ALIGNVAL)), &hAccessor, bds))){
512             //dbs是绑定状态
513             break;
514         }
515 
516         return S_OK;
517     } while (0);
518 
519     ReleaseRowsetFastLoadAndIAccessor(pIRowsetFastLoad, pIAccessor, hAccessor);
520     return E_FAIL;
521 }
522 
523 HRESULT CNativeClientOLEDB::ReleaseRowsetAndIAccessor(IRowset** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor)
524 {
525     HRESULT hr = S_OK;
526     if (*pIRowset){
527         (*pIRowset)->Release();
528         (*pIRowset) = NULL;
529     }
530 
531     if (*pIAccessor && hAccessor){
532         if (FAILED((*pIAccessor)->ReleaseAccessor(hAccessor, NULL))){
533             hr = E_FAIL;
534         }
535         (*pIAccessor)->Release();
536         *pIAccessor = NULL;
537     }
538 
539     return hr;
540 }
541 
542 HRESULT CNativeClientOLEDB::ReleaseRowsetFastLoadAndIAccessor(IRowsetFastLoad** pIRowset,IAccessor** pIAccessor,const HACCESSOR& hAccessor)
543 {
544 
545     HRESULT hr = S_OK;
546     if (FAILED(hr = SetFastLoadProperty(FALSE)))
547         printf("SetFastLoadProperty(FALSE) failed with %x", hr);
548 
549     if (*pIAccessor && hAccessor)
550         if (FAILED((*pIAccessor)->ReleaseAccessor(hAccessor, NULL)))
551             hr = E_FAIL;
552 
553     if (*pIAccessor){
554         (*pIAccessor)->Release();
555         *pIAccessor = NULL;
556     }
557 
558     if (*pIRowset){
559         (*pIRowset)->Release();
560         (*pIRowset) = NULL;
561     }
562 
563     if (TableID.uName.pwszName)
564         delete[]TableID.uName.pwszName;
565 
566     return hr;
567 }
568 
569 HRESULT CNativeClientOLEDB::CreateSessionAndCommand()
570 {
571     HRESULT hr = E_FAIL;
572     if (NULL == m_pIDBInitialize || m_pIDBSession || m_pIOpenRowset || m_pIDBCreateCommand || m_pICommand || m_pICommandText){
573         return hr;
574     }
575 
576     do 
577     {
578         if (FAILED(hr =
579             m_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void **)&m_pIDBSession)))
580             break;
581 
582         if (FAILED(hr =
583             m_pIDBSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown **)&m_pIOpenRowset )))
584             break;
585 
586         if (FAILED(hr = m_pIOpenRowset ->QueryInterface(IID_IDBCreateCommand, (void **)&m_pIDBCreateCommand))){
587             break;
588         }
589 
590         if (FAILED(hr =    m_pIDBCreateCommand->CreateCommand(NULL, IID_ICommand, (IUnknown **)&m_pICommand))){
591                 break;
592         }
593 
594         if (FAILED(hr = m_pICommand->QueryInterface(&m_pICommandText))){
595             break;
596         }
597 
598         return S_OK;
599 
600     } while (0);
601     
602     ReleaseSessionAndCommand();
603     return hr;
604 }
605 
606 HRESULT CNativeClientOLEDB::ReleaseSessionAndCommand()
607 {
608     HRESULT hr = S_OK;
609     if (m_pICommandText){
610         m_pICommandText->Release();
611         m_pICommandText = NULL;
612     }
613 
614     if (m_pICommand){
615         m_pICommand->Release();
616         m_pICommand = NULL;
617     }
618 
619     if (m_pIDBCreateCommand){
620         m_pIDBCreateCommand->Release();
621         m_pIDBCreateCommand = NULL;
622     }
623 
624     if (m_pIOpenRowset){
625         m_pIOpenRowset->Release();
626         m_pIOpenRowset = NULL;
627     }
628 
629     if (m_pIDBSession){
630         m_pIDBSession->Release();
631         m_pIDBSession = NULL;
632     }
633 
634     return S_OK;
635 }
636 
637 HRESULT CNativeClientOLEDB::SetPropertiesAndCreateSessionAndIOpenRowset(BOOL bFast /*= TRUE*/)
638 {
639     HRESULT hr;
640     if (NULL == m_pIDBInitialize){
641         return E_FAIL;
642     }
643     do 
644     {
645         if (FAILED(hr = SetFastLoadProperty(bFast)))
646             break;
647 
648         if (FAILED(hr =
649             m_pIDBInitialize->QueryInterface(IID_IDBCreateSession, (void **)&m_pIDBSession)))
650             break;
651 
652         if (FAILED(hr =
653             m_pIDBSession->CreateSession(NULL, IID_IOpenRowset, (IUnknown **)&m_pIOpenRowset)))
654             break;
655 
656         return S_OK;
657     } while (0);
658     // Get the fastload pointer.
659     
660     ReleaseSessionIOpenRowset();
661     return E_FAIL;
662 }
663 
664 HRESULT CNativeClientOLEDB::ReleaseSessionIOpenRowset()
665 {
666     if (m_pIDBSession){
667         m_pIDBSession->Release();
668         m_pIDBSession = NULL;
669     }
670 
671     if (m_pIOpenRowset){
672         m_pIOpenRowset->Release();
673         m_pIOpenRowset = NULL;
674     }
675     return S_OK;
676 }
View Code

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

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

  1 #pragma once
  2 #include <OLEDB/NativeClientOLEDB.h>
  3 
  4 #pragma pack(push, 1)
  5 class HistoryData : 
  6     public Data{
  7 public:
  8     /*
  9     SDWORD SOID_len;   // Length of data (not space allocated).
 10     DWORD SOID_status;   // Status of column.
 11     int SOID_value;
 12 
 13     SDWORD TerminalID_len;   // Length of data (not space allocated).
 14     DWORD TerminalID_status;   // Status of column.
 15     int TerminalID_value;
 16     */
 17     SDWORD Longitude_len;   // Length of data (not space allocated).
 18     DWORD Longitude_status;   // Status of column.
 19     int Longitude_value;
 20 
 21     SDWORD Latitude_len;   // Length of data (not space allocated).
 22     DWORD Latitude_status;   // Status of column.
 23     int Latitude_value;
 24 
 25     SDWORD Speed_len;   // Length of data (not space allocated).
 26     DWORD Speed_status;   // Status of column.
 27     WORD Speed_value;
 28 
 29     //
 30 
 31     SDWORD Direction_len;   // Length of data (not space allocated).
 32     DWORD Direction_status;   // Status of column.
 33     WORD Direction_value;
 34 
 35     SDWORD Height_len;   // Length of data (not space allocated).
 36     DWORD Height_status;   // Status of column.
 37     short Height_value;
 38 
 39     SDWORD Lock_len;   // Length of data (not space allocated).
 40     DWORD Lock_status;   // Status of column.
 41     BYTE Lock_value;
 42 
 43 
 44     SDWORD Gpstime_len;   // Length of data (not space allocated).
 45     DWORD Gpstime_status;   // Status of column.
 46     char Gpstime_value[30];
 47 
 48     SDWORD InStatus_len;   // Length of data (not space allocated).
 49     DWORD InStatus_status;   // Status of column.
 50     short InStatus_value;
 51 
 52     //
 53     SDWORD TmlStatus_len;   // Length of data (not space allocated).
 54     DWORD TmlStatus_status;   // Status of column.
 55     short TmlStatus_value;
 56 
 57     SDWORD WarnFlag_len;   // Length of data (not space allocated).
 58     DWORD WarnFlag_status;   // Status of column.
 59     short WarnFlag_value;
 60 
 61     SDWORD Resver2_len;   // Length of data (not space allocated).
 62     DWORD Resver2_status;   // Status of column.
 63     short Resver2_value;
 64 
 65     SDWORD Alldis_len;   // Length of data (not space allocated).
 66     DWORD Alldis_status;   // Status of column.
 67     int Alldis_value;
 68 
 69     SDWORD Temperature_len;   // Length of data (not space allocated).
 70     DWORD Temperature_status;   // Status of column.
 71     int Temperature_value;
 72 
 73     //
 74     SDWORD Oil_len;   // Length of data (not space allocated).
 75     DWORD Oil_status;   // Status of column.
 76     short Oil_value;
 77 
 78     SDWORD Smsid1_len;   // Length of data (not space allocated).
 79     DWORD Smaid1_status;   // Status of column.
 80     short Smaid1_value;
 81 
 82     SDWORD Smaid2_len;   // Length of data (not space allocated).
 83     DWORD Smaid2_status;   // Status of column.
 84     short Smaid2_value;
 85     /*
 86     SDWORD Longitude2_len;   // Length of data (not space allocated).
 87     DWORD Longitude2_status;   // Status of column.
 88     int Longitude2_value;
 89 
 90     SDWORD Latitude2_len;   // Length of data (not space allocated).
 91     DWORD Latitude2_status;   // Status of column.
 92     int Latitude2_value;
 93     */
 94     //
 95     SDWORD AffixData_len;   // Length of data (not space allocated).
 96     DWORD AffixData_status;   // Status of column.
 97     char AffixData_value[2000];
 98 };
 99 #pragma pack(pop)
100 
101 class CHistoryDataOLEDB :
102     public CNativeClientOLEDB
103 {
104 public:
105     CHistoryDataOLEDB(void);
106     ~CHistoryDataOLEDB(void);
107 
108     virtual void SetColType(void);
109 
110     virtual void SetColLen(void);
111 
112     virtual void set_bindings();
113 
114     void Lock()        {    cs.Lock();        };
115     void Unlock()    {    cs.Unlock();    };
116 
117 public:
118     //快速查询数据
119     LPBYTE FastQueryData(CStringW strSql,ULONG nColNum, int* nLen, int* nCount);
120     //快速插入数据
121     BOOL FastInsertData(const CStringW strTable, HistoryData* const pData, const int nDataNum);
122 
123 private:
124     CCriticalSection cs;
125 };
View Code

//HistoryDataOLEDB.cpp

  1 #include "StdAfx.h"
  2 #include "HistoryDataOLEDB.h"
  3 #include "HistoryDefine.h"
  4 #include "Base64.h"
  5 
  6 CHistoryDataOLEDB::CHistoryDataOLEDB(void)
  7 {
  8     SetColLen();
  9     SetColType();
 10 }
 11 
 12 
 13 CHistoryDataOLEDB::~CHistoryDataOLEDB(void)
 14 {
 15 }
 16 
 17 void CHistoryDataOLEDB::SetColType(void)
 18 {
 19     col_type[0] = DBTYPE_I4;
 20     col_type[1] = DBTYPE_I4;
 21     col_type[2] = DBTYPE_I4;
 22     col_type[3] = DBTYPE_I4;
 23     col_type[4] = DBTYPE_I2;
 24 
 25     col_type[5] = DBTYPE_I2;
 26     col_type[6] = DBTYPE_I2;
 27     col_type[7] = DBTYPE_UI1;
 28     col_type[8] = DBTYPE_STR;
 29     col_type[9] = DBTYPE_I2;
 30 
 31     col_type[10] = DBTYPE_I2;
 32     col_type[11] = DBTYPE_I2;
 33     col_type[12] = DBTYPE_I2;
 34     col_type[13] = DBTYPE_I4;
 35     col_type[14] = DBTYPE_I4;
 36 
 37     col_type[15] = DBTYPE_I2;
 38     col_type[16] = DBTYPE_I2;
 39     col_type[17] = DBTYPE_I2;
 40     col_type[18] = DBTYPE_I4;
 41     col_type[19] = DBTYPE_I4;
 42 
 43     col_type[20] = DBTYPE_STR;
 44 }
 45 
 46 void CHistoryDataOLEDB::SetColLen(void)
 47 {
 48     col_len[0] = sizeof(int);
 49     col_len[1] = sizeof(int);
 50     col_len[2] = sizeof(int);
 51     col_len[3] = sizeof(int);
 52     col_len[4] = sizeof(short);
 53 
 54     col_len[5] = sizeof(short);
 55     col_len[6] = sizeof(short);
 56     col_len[7] = sizeof(char);
 57     col_len[8] = 30;
 58     col_len[9] = sizeof(short);
 59 
 60     col_len[10] = sizeof(short);
 61     col_len[11] = sizeof(short);
 62     col_len[12] = sizeof(short);
 63     col_len[13] = sizeof(int);
 64     col_len[14] = sizeof(int);
 65 
 66     col_len[15] = sizeof(short);
 67     col_len[16] = sizeof(short);
 68     col_len[17] = sizeof(short);
 69     col_len[18] = sizeof(int);
 70     col_len[19] = sizeof(int);
 71 
 72     col_len[20] = 2000;
 73 }
 74 
 75 void CHistoryDataOLEDB::set_bindings()
 76 {
 77     set_bind(m_bindings[0], 1, offsetof(HistoryData, Longitude_len), offsetof(HistoryData, Longitude_status), offsetof(HistoryData, Longitude_value), col_len[2], col_type[2]);
 78     set_bind(m_bindings[1], 2, offsetof(HistoryData, Latitude_len), offsetof(HistoryData, Latitude_status), offsetof(HistoryData, Latitude_value), col_len[3], col_type[3]);
 79     set_bind(m_bindings[2], 3, offsetof(HistoryData, Speed_len), offsetof(HistoryData, Speed_status), offsetof(HistoryData, Speed_value), col_len[4], col_type[4]);
 80 
 81     set_bind(m_bindings[3], 4, offsetof(HistoryData, Direction_len), offsetof(HistoryData, Direction_status), offsetof(HistoryData, Direction_value), col_len[5], col_type[5]);
 82     set_bind(m_bindings[4], 5, offsetof(HistoryData, Height_len), offsetof(HistoryData, Height_status), offsetof(HistoryData, Height_value), col_len[6], col_type[6]);
 83     set_bind(m_bindings[5], 6, offsetof(HistoryData, Lock_len), offsetof(HistoryData, Lock_status), offsetof(HistoryData, Lock_value), col_len[7], col_type[7]);
 84     set_bind(m_bindings[6], 7, offsetof(HistoryData, Gpstime_len), offsetof(HistoryData, Gpstime_status), offsetof(HistoryData, Gpstime_value), col_len[8], col_type[8]);
 85     set_bind(m_bindings[7], 8, offsetof(HistoryData, InStatus_len), offsetof(HistoryData, InStatus_status), offsetof(HistoryData, InStatus_value), col_len[9], col_type[9]);
 86 
 87     set_bind(m_bindings[8], 9, offsetof(HistoryData, TmlStatus_len), offsetof(HistoryData, TmlStatus_status), offsetof(HistoryData, TmlStatus_value), col_len[10], col_type[10]);
 88     set_bind(m_bindings[9], 10, offsetof(HistoryData, WarnFlag_len), offsetof(HistoryData, WarnFlag_status), offsetof(HistoryData, WarnFlag_value), col_len[11], col_type[11]);
 89     set_bind(m_bindings[10], 11, offsetof(HistoryData, Resver2_len), offsetof(HistoryData, Resver2_status), offsetof(HistoryData, Resver2_value), col_len[12], col_type[12]);
 90     set_bind(m_bindings[11], 12, offsetof(HistoryData, Alldis_len), offsetof(HistoryData, Alldis_status), offsetof(HistoryData, Alldis_value), col_len[13], col_type[13]);
 91     set_bind(m_bindings[12], 13, offsetof(HistoryData, Temperature_len), offsetof(HistoryData, Temperature_status), offsetof(HistoryData, Temperature_value), col_len[14], col_type[14]);
 92 
 93     set_bind(m_bindings[13], 14, offsetof(HistoryData, Oil_len), offsetof(HistoryData, Oil_status), offsetof(HistoryData, Oil_value), col_len[15], col_type[15]);
 94     set_bind(m_bindings[14], 15, offsetof(HistoryData, Smsid1_len), offsetof(HistoryData, Smaid1_status), offsetof(HistoryData, Smaid1_value), col_len[16], col_type[16]);
 95     set_bind(m_bindings[15], 16, offsetof(HistoryData, Smaid2_len), offsetof(HistoryData, Smaid2_status), offsetof(HistoryData, Smaid2_value), col_len[17], col_type[17]);
 96 
 97     set_bind(m_bindings[16], 17, offsetof(HistoryData, AffixData_len), offsetof(HistoryData, AffixData_status), offsetof(HistoryData, AffixData_value), col_len[20], col_type[20]);
 98 
 99 }
100 
101 LPBYTE CHistoryDataOLEDB::FastQueryData(CStringW strSql,ULONG nColNum, int* nLen, int* nCount)
102 {
103     HRESULT hr = E_FAIL;
104     HistoryData rmd;            //历史数据
105     HROW* rghRows = NULL;
106     LONG cRows = 100;        //一次读取10行
107     ULONG uRowsObtained = 0;    //实际读取的条数
108 
109     IRowset *pIRowset = NULL;
110     IAccessor* pIAccessor = NULL;
111     HACCESSOR hAccessor = DB_NULL_HACCESSOR;
112     if (S_OK != (hr = CNativeClientOLEDB::FastQueryData(strSql, nColNum, &pIRowset, &pIAccessor, hAccessor))){
113         return NULL;
114     }
115     LPBYTE lpData = new BYTE[10 * 1024 * 1024];
116     ZeroMemory(lpData, 10 * 1024 * 1024);
117     int nDataLen = 0;
118     int nDataCount = 0;
119     while (FALSE == FAILED(hr = pIRowset->GetNextRows( DB_NULL_HCHAPTER, 0, cRows, &uRowsObtained, &rghRows)))
120     {
121         int j = 0;
122         if (cRows != uRowsObtained){
123             printf("cRows != uRowsObtained.
");
124         }
125 
126         for (int i = 0; i < uRowsObtained; ++i){
127             if (FAILED( hr = pIRowset->GetData(rghRows[i], hAccessor, &rmd )))
128             {
129                 printf("获取数据失败 %d .
", i);
130                 break;
131                 //std::cout << "获取数据失败." << std::endl;
132             }
133 
134             if (rmd.AffixData_status != 0 || rmd.Alldis_status != 0 || rmd.Direction_status != 0 || rmd.Gpstime_status != 0 ||
135                 rmd.Height_status != 0 || rmd.InStatus_status != 0 || rmd.Latitude_status != 0 || rmd.Latitude_status != 0 || rmd.Lock_status != 0 ||
136                 rmd.Oil_status != 0 || rmd.Speed_status != 0 || rmd.Direction_status != 0 ||
137                 rmd.Resver2_status != 0 || rmd.Smaid1_status != 0 || rmd.Smaid2_status != 0 || rmd.Temperature_status != 0 || 
138                 rmd.WarnFlag_status != 0){
139                     ASSERT(0);
140                     break;
141             }
142 
143             HistoryGPSData gpsdata;
144             memset(&gpsdata, 0, sizeof(HistoryGPSData));
145             gpsdata.longitude = rmd.Longitude_value;
146             gpsdata.latitude = rmd.Latitude_value;
147             gpsdata.speed = rmd.Speed_value;
148             gpsdata.direction = rmd.Direction_value;
149             gpsdata.gpsHeight = rmd.Height_value;
150             gpsdata.byLock = rmd.Lock_value;
151             //TRACE("%s
", rmd.Gpstime_value);
152             SYSTEMTIME sysGps;
153             sscanf(rmd.Gpstime_value, "%d-%d-%d %d:%d:%d", &sysGps.wYear, &sysGps.wMonth, &sysGps.wDay, &sysGps.wHour, &sysGps.wMinute, &sysGps.wSecond);
154             gpsdata.gpstm[0] = sysGps.wYear - 2000;
155             gpsdata.gpstm[1] = sysGps.wMonth;
156             gpsdata.gpstm[2] = sysGps.wDay;
157             gpsdata.gpstm[3] = sysGps.wHour;
158             gpsdata.gpstm[4] = sysGps.wMinute;
159             gpsdata.gpstm[5] = sysGps.wSecond;
160             int nInStatus = rmd.InStatus_value;
161             gpsdata.InStatus1 = nInStatus & 0xFF;
162             gpsdata.InStatus2 = (nInStatus >> 8) & 0xFF;
163             int nTmlStatus = rmd.TmlStatus_value;
164             gpsdata.TmlStatus1 = nTmlStatus & 0xFF;
165             gpsdata.TmlStatus2 = (nTmlStatus >> 8) & 0xFF;
166             int nWarnFlag = rmd.WarnFlag_value;
167             gpsdata.WarnFlag1 = nWarnFlag & 0xFF;
168             gpsdata.WarnFlag2 = (nWarnFlag >> 8) & 0xFF;
169             int resver2 = rmd.Resver2_value;
170             gpsdata.extflag = resver2 &0xFF;
171             gpsdata.netid = (resver2 >> 8) & 0xFF;
172             gpsdata.alldis = rmd.Alldis_value;
173             int nTemperatue = rmd.Temperature_value;
174             memcpy(gpsdata.temperture, &nTemperatue, 4);
175             gpsdata.oil = rmd.Oil_value;
176             gpsdata.cellid = rmd.Smaid2_value;
177             gpsdata.lacid = rmd.Smaid1_value;
178             CString strAffixData = rmd.AffixData_value;
179 
180             gpsdata.longitude = htonl(gpsdata.longitude);
181             gpsdata.latitude = htonl(gpsdata.latitude);
182             gpsdata.speed = htons(gpsdata.speed);
183             gpsdata.direction = htons(gpsdata.direction);
184             gpsdata.gpsHeight = htons(gpsdata.gpsHeight);
185             gpsdata.alldis = htonl(gpsdata.alldis);
186             gpsdata.oil = htons(gpsdata.oil);
187             gpsdata.cellid = htons(gpsdata.cellid);
188             gpsdata.lacid = htons(gpsdata.lacid);
189 
190             nDataCount++;
191             memcpy(lpData + nDataLen, &gpsdata, sizeof(HistoryGPSData));
192             nDataLen += sizeof(HistoryGPSData);
193 
194             //写入扩展数据
195             if(!strAffixData.IsEmpty())
196             {
197                 BYTE bAffixData[4096] = {0};
198                 int nSrcLen = strAffixData.GetLength();
199                 LPBYTE pSrcData = (LPBYTE)strAffixData.GetBuffer();
200                 int nAffixLen = base64_decode(bAffixData, pSrcData, nSrcLen);
201                 strAffixData.ReleaseBuffer();
202                 if(nAffixLen > 2)
203                 {
204                     int nTmpLen = nAffixLen - 2;
205                     bAffixData[0] = (nTmpLen >> 8) & 0xFF;
206                     bAffixData[1] = nTmpLen & 0xFF;
207                     memcpy(lpData + nDataLen, bAffixData, nAffixLen);
208                     nDataLen += nAffixLen;
209                 }
210             }
211         }
212 
213         if (uRowsObtained){
214             pIRowset->ReleaseRows(uRowsObtained, rghRows, NULL, NULL, NULL);
215         }
216         //释放
217         CoTaskMemFree(rghRows);
218         rghRows = NULL;
219 
220         if (hr == DB_S_ENDOFROWSET){
221             printf("数据已经全部读取完成共计:%d 条.", nDataCount);
222             break;
223         }
224     }
225 
226     //释放 IRowSet 和 IAccessor
227     ReleaseRowsetAndIAccessor(&pIRowset, &pIAccessor, hAccessor);
228 
229     if (0 == nDataLen){
230         delete[] lpData;
231         lpData = NULL;
232         nDataCount = 0;
233         nDataLen = 0;
234     }
235     *nLen = nDataLen;
236     *nCount = nDataCount;
237     return lpData;
238 }
239 
240 BOOL CHistoryDataOLEDB::FastInsertData(const CStringW strTable, HistoryData* const pData, const int nDataNum)
241 {
242     if (NULL == pData || 0 == nDataNum || strTable.IsEmpty()){
243         return TRUE;
244     }
245 
246     HRESULT hr = NOERROR;
247     IRowsetFastLoad * pIRowsetFastLoad = NULL;
248     IAccessor* pIAccessor = NULL;
249     HACCESSOR hAccessor = 0;
250     ULONG nColNum = 21;
251     if (S_OK != (hr = CNativeClientOLEDB::FastInsertData(strTable, nColNum, &pIRowsetFastLoad, &pIAccessor, hAccessor))){
252         return FALSE;
253     }
254     BOOL bRet = TRUE;
255     for (int i = 0; i < nDataNum; i++){
256         if (FAILED(hr = pIRowsetFastLoad->InsertRow(hAccessor, &pData[i])))
257         {
258 
259             DumpErrorInfo(pIRowsetFastLoad, IID_ISQLServerErrorInfo);
260             bRet = TRUE;
261             break;
262         }
263     }
264     //全部插入之后,提交一次
265     if (FAILED(hr = pIRowsetFastLoad->Commit(TRUE)))
266     {
267         DumpErrorInfo(pIRowsetFastLoad, IID_ISQLServerErrorInfo);
268         bRet = TRUE;
269         printf("Error on IRFL::Commit
");
270     }
271     
272     ReleaseRowsetFastLoadAndIAccessor(&pIRowsetFastLoad, &pIAccessor, hAccessor);
273     if (bRet){
274         return FALSE;
275     } else {
276         return TRUE;
277     }
278 }
View Code

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

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

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

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

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

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

5. 释放 IRowSet 和 IAccessor

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

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

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

//CNativeClientOLEDBPool.h

  1 #pragma once
  2 
  3 #include <list>
  4 using namespace std;
  5 
  6 template <class T>
  7 class CNativeClientOLEDBPool
  8 {
  9 public:
 10     CNativeClientOLEDBPool(void){
 11         m_hSemaphore = NULL;
 12         m_nMaxCount = 1;
 13     }
 14     ~CNativeClientOLEDBPool(void){
 15         Clear();
 16     }
 17     //static CNativeClientOLEDBPool* Instance() { return &m_Instance; }
 18 
 19     //nCount连接数
 20     HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG, int nCount = 1){
 21         HRESULT hr = S_OK;
 22         ASSERT(nCount >= 1);
 23         m_hSemaphore = ::CreateSemaphore(NULL, nCount, 0x7FFFFFFF, NULL);
 24 
 25         m_cs.Lock();
 26         m_nMaxCount = nCount;
 27         m_strDataSource = strDataSource;
 28         m_strUserID = strUserID;
 29         m_strPassWD = strPassWD;
 30         m_strCataLOG = strCataLOG;
 31 
 32         for(int i=0; i<m_nMaxCount; i++){
 33             T* pConn = new T;
 34             if (S_OK == (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))){
 35                 m_pConnList.push_back(pConn);
 36             } else {
 37                 delete pConn;
 38                 break;
 39             }
 40         }
 41         if(m_pConnList.size() != m_nMaxCount){
 42             ASSERT(0);
 43         } 
 44         m_cs.Unlock();
 45         return hr;
 46     }
 47 
 48     void Clear(){
 49         if(m_hSemaphore)
 50         {
 51             ::CloseHandle(m_hSemaphore);
 52             m_hSemaphore = NULL;
 53         }
 54 
 55         m_cs.Lock();
 56 
 57         m_nMaxCount = 0;
 58         list<T*>::iterator it = m_pConnList.begin();
 59         for(; it != m_pConnList.end(); it++)
 60         {
 61             T* pConn = *it;
 62             if(pConn)
 63             {
 64                 pConn->UnInit();
 65                 delete pConn;
 66             }
 67         }
 68         m_pConnList.clear();
 69 
 70         m_cs.Unlock();
 71     }
 72 
 73     T* GetConnection(){
 74         T* pConn = NULL;
 75         if(::WaitForSingleObject(m_hSemaphore, INFINITE) != WAIT_OBJECT_0)
 76             return pConn;
 77 
 78         m_cs.Lock();
 79         if(!m_pConnList.empty())
 80         {
 81             pConn = m_pConnList.front();
 82             m_pConnList.pop_front();
 83         }
 84         m_cs.Unlock();
 85 
 86         if(pConn == NULL)
 87         {
 88             //create new database connection
 89             pConn = new T();
 90             HRESULT hr = NOERROR;
 91             if(S_OK != (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))) {
 92                 delete pConn;
 93                 pConn = NULL;
 94             }
 95         }
 96         return pConn;
 97     }
 98     void FreeConnection(T* pConn){
 99         ASSERT(pConn != NULL);
100 
101         BOOL bSemaphore = FALSE;
102 
103         m_cs.Lock();
104         if(m_pConnList.size() >= m_nMaxCount)
105         {
106             pConn->UnInit();
107             delete pConn;
108         }
109         else
110         {
111             m_pConnList.push_back(pConn);
112             bSemaphore = TRUE;
113         }
114         m_cs.Unlock();
115 
116         if(bSemaphore)
117         {
118             ::ReleaseSemaphore(m_hSemaphore, 1, NULL);
119         }
120     }
121 
122 public:
123     BOOL ReOpenConnection(T* pConn){
124         return FALSE;
125     }
126 
127     BOOL VerifyConnection(T* pConn){
128         return TRUE;
129     }
130 
131 protected:
132     int m_nMaxCount;
133     CStringW m_strDataSource;
134     CStringW m_strUserID;
135     CStringW m_strPassWD;
136     CStringW m_strCataLOG;
137     CCriticalSection m_cs;
138     list<T*> m_pConnList;
139 
140     HANDLE m_hSemaphore;
141     //static CNativeClientOLEDBPool m_Instance;
142 };
143 
144  
145 
146  
147 
148 #pragma once
149 
150 #include <list>
151 using namespace std;
152 
153 template <class T>
154 class CNativeClientOLEDBPool
155 {
156 public:
157     CNativeClientOLEDBPool(void){
158         m_hSemaphore = NULL;
159         m_nMaxCount = 1;
160     }
161     ~CNativeClientOLEDBPool(void){
162         Clear();
163     }
164     //static CNativeClientOLEDBPool* Instance() { return &m_Instance; }
165 
166     //nCount连接数
167     HRESULT Init(CStringW strDataSource, CStringW strUserID, CStringW strPassWD, CStringW strCataLOG, int nCount = 1){
168         HRESULT hr = S_OK;
169         ASSERT(nCount >= 1);
170         m_hSemaphore = ::CreateSemaphore(NULL, nCount, 0x7FFFFFFF, NULL);
171 
172         m_cs.Lock();
173         m_nMaxCount = nCount;
174         m_strDataSource = strDataSource;
175         m_strUserID = strUserID;
176         m_strPassWD = strPassWD;
177         m_strCataLOG = strCataLOG;
178 
179         for(int i=0; i<m_nMaxCount; i++){
180             T* pConn = new T;
181             if (S_OK == (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))){
182                 m_pConnList.push_back(pConn);
183             } else {
184                 delete pConn;
185                 break;
186             }
187         }
188         if(m_pConnList.size() != m_nMaxCount){
189             ASSERT(0);
190         } 
191         m_cs.Unlock();
192         return hr;
193     }
194 
195     void Clear(){
196         if(m_hSemaphore)
197         {
198             ::CloseHandle(m_hSemaphore);
199             m_hSemaphore = NULL;
200         }
201 
202         m_cs.Lock();
203 
204         m_nMaxCount = 0;
205         list<T*>::iterator it = m_pConnList.begin();
206         for(; it != m_pConnList.end(); it++)
207         {
208             T* pConn = *it;
209             if(pConn)
210             {
211                 pConn->UnInit();
212                 delete pConn;
213             }
214         }
215         m_pConnList.clear();
216 
217         m_cs.Unlock();
218     }
219 
220     T* GetConnection(){
221         T* pConn = NULL;
222         if(::WaitForSingleObject(m_hSemaphore, INFINITE) != WAIT_OBJECT_0)
223             return pConn;
224 
225         m_cs.Lock();
226         if(!m_pConnList.empty())
227         {
228             pConn = m_pConnList.front();
229             m_pConnList.pop_front();
230         }
231         m_cs.Unlock();
232 
233         if(pConn == NULL)
234         {
235             //create new database connection
236             pConn = new T();
237             HRESULT hr = NOERROR;
238             if(S_OK != (hr = pConn->Init(m_strDataSource, m_strUserID, m_strPassWD, m_strCataLOG))) {
239                 delete pConn;
240                 pConn = NULL;
241             }
242         }
243         return pConn;
244     }
245     void FreeConnection(T* pConn){
246         ASSERT(pConn != NULL);
247 
248         BOOL bSemaphore = FALSE;
249 
250         m_cs.Lock();
251         if(m_pConnList.size() >= m_nMaxCount)
252         {
253             pConn->UnInit();
254             delete pConn;
255         }
256         else
257         {
258             m_pConnList.push_back(pConn);
259             bSemaphore = TRUE;
260         }
261         m_cs.Unlock();
262 
263         if(bSemaphore)
264         {
265             ::ReleaseSemaphore(m_hSemaphore, 1, NULL);
266         }
267     }
268 
269 public:
270     BOOL ReOpenConnection(T* pConn){
271         return FALSE;
272     }
273 
274     BOOL VerifyConnection(T* pConn){
275         return TRUE;
276     }
277 
278 protected:
279     int m_nMaxCount;
280     CStringW m_strDataSource;
281     CStringW m_strUserID;
282     CStringW m_strPassWD;
283     CStringW m_strCataLOG;
284     CCriticalSection m_cs;
285     list<T*> m_pConnList;
286 
287     HANDLE m_hSemaphore;
288     //static CNativeClientOLEDBPool m_Instance;
289 };
View Code

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

感谢这两位大牛.

原文地址:https://www.cnblogs.com/SamRichard/p/5550050.html