ADO技术访问数据库

来源:互联网 发布:java尚学堂马士兵微盘 编辑:程序博客网 时间:2024/04/30 21:37
用VC和ADO技术访问数据库,该数据库中某个待访问的表有100万条记录。现在一条select查询语句要求返回该表中的所有记录。为了让用户能够及时地得到反馈信息,而不是在ADO取完这100万条记录之后才将信息返回给用户,假设我们以每次1000条记录为单位向用户返回数据,即ADO检索完前1000条记录后,就将这1000条记录数据返回给用户同时它继续取检索后1000条记录,依此方式取记录,直到取完数据库中的所有记录为止。于是我的程序代码如下:  
  void   CAccessDBDlg::OnQuery()    
  {  
          HRESULT   hr;  
          _ConnectionPtr   pConn;  
          _RecordsetPtr   pRst;  
          DWORD       dwConnEvt;  
          DWORD       dwRstEvt;  
          IConnectionPointContainer*   pCPC   =   NULL;  
          IConnectionPoint*   pCP   =   NULL;  
          IUnknown*   pUnk   =   NULL;  
          CConnEvent*   pConnEvent=   NULL;  
          CRstEvent*   pRstEvent   =   NULL;  
   
          //Initialize  
          hr   =   ::CoInitialize(NULL);  
          hr   =   pConn.CreateInstance(__uuidof(Connection));  
          hr   =   pRst.CreateInstance(__uuidof(Recordset));  
   
          //Start   using   the   Connection   events  
          hr   =   pConn->QueryInterface(__uuidof(IConnectionPointContainer),    
              (void   **)&pCPC);  
          if   (FAILED(hr))   return   ;  
          hr   =   pCPC->FindConnectionPoint(__uuidof(ConnectionEvents),   &pCP);  
              pCPC->Release();  
          if   (FAILED(hr))   return   ;  
          pConnEvent   =   new   CConnEvent();  
          hr   =   pConnEvent->QueryInterface(__uuidof(IUnknown),   (void   **)   &pUnk);  
          if   (FAILED(hr))   return   ;  
          hr   =   pCP->Advise(pUnk,   &dwConnEvt);  
          pCP->Release();  
          if   (FAILED(hr))   return   ;  
   
          //Start   using   the   Recordset   events  
          hr   =   pRst->QueryInterface(__uuidof(IConnectionPointContainer),  
              (void   **)&pCPC);  
          if   (FAILED(hr))   return   ;  
          hr   =   pCPC->FindConnectionPoint(__uuidof(RecordsetEvents),   &pCP);  
          pCPC->Release();  
          if   (FAILED(hr))   return   ;  
          pRstEvent   =   new   CRstEvent();  
          hr   =   pRstEvent->QueryInterface(__uuidof(IUnknown),   (void   **)   &pUnk);  
          if   (FAILED(hr))   return   ;  
          hr   =   pCP->Advise(pUnk,   &dwRstEvt);  
          pCP->Release();  
          if   (FAILED(hr))   return   ;  
   
          //Set   recordset   property  
          PropertiesPtr   pProperties;  
          PropertyPtr   pProperty;  
          VARIANT   varIndex,varValue;  
          varIndex.vt   =   VT_BSTR;  
          varValue.vt   =   VT_I4;  
   
          pRst->put_CursorLocation(adUseClient);  
          pRst->get_Properties(&pProperties);  
          varIndex.bstrVal   =   ::SysAllocString(L"Initial   Fetch   Size");  
          pProperties->get_Item(varIndex,&pProperty);  
          varValue.lVal   =   1000;  
          pProperty->put_Value(varValue);  
          varIndex.bstrVal   =   ::SysAllocString(L"Background   Fetch   Size");  
          pProperties->get_Item(varIndex,&pProperty);  
          varValue.lVal   =   1000;  
          pProperty->put_Value(varValue);  
   
          //Open   connection  
          BSTR   bstrConnectionString   =   ::SysAllocString(L"Provider=SQLOLEDB.1;Password=billtw;Persist   Security   Info=True;User   ID=sa;Initial   Catalog=WingingDB;Data   Source=WEITAO");  
          pConn->Open(bstrConnectionString,"","",-1);  
   
          //Open   recordset  
          VARIANT   varConnString,varCommandText;  
          varConnString.vt   =   VT_DISPATCH;  
          varConnString.pdispVal   =   pConn;  
          varCommandText.vt   =   VT_BSTR;  
          varCommandText.bstrVal   =   ::SysAllocString(L"select   *   from   cardnumber");  
          pRst->Open(varCommandText,varConnString,adOpenStatic,adLockOptimistic,adCmdText   |   adAsyncFetch);  
   
          //Close   recordset   and   connection  
          pRst->Close();  
          pConn->Close();  
  }  
   
  Recordset对象的FetchProgress事件处理函数如下:  
  STDMETHODIMP   CRstEvent::raw_FetchProgress(  
                    long   Progress,  
                    long   MaxProgress,  
                    EventStatusEnum   *adStatus,  
                    struct   _Recordset   *pRecordset)  
                    {  
            CString   strRecordsetCount;  
            long   lRecordCount;  
            pRecordset->get_RecordCount(&lRecordCount);  
            strRecordsetCount.Format("Fetch   progress   %d",lRecordCount);  
            AfxMessageBox(strRecordsetCount);  
                              return   S_OK;  
                    };  
   
          现在的问题是,从理论上说,既然Recordset对象动态属性集中的Initial   Fetch   Size和Background   Fetch   Size属性被设置为1000,且Recordset是以adAsyncFetch方式打开的,那么FetchProgress事件就应该被触发100次(100万记录数/1000),且每次触发时,pRecordset中记录了取得的1000条记录。可是我实际运行时,FetchProgress事件只被触发了一次(只显示了一次AfxMessageBox中的内容),且此时得到的lRecordCount值为1000000,实际的运行结果似乎和理论上的不一致,这是什么原因呢?如果这种方法不行,我又该以什么方法来实现我上述的需求呢?
原创粉丝点击