ADO ( 问数据库数据 的编程 接口)

  • ADO  (ActiveX Data Objects)  
  • ADO有三个智能指针:_ConnectionPtr连接对象 、_RecordsetPtr记录集对象、_CommandPtr命令对象
  • 先创建SQL记录集,从记录集中提取数据;
  • step1:引入ADO类(在 StdAfx.h   中加入)
1 /*忽略ADO的警告*/
2 #pragma warning(disable: 4146)
3 #pragma warning(disable: 4244)
4 
5 /*ADO需要导入的库*/
6 #import "C:\Program Files\Common Files\SYSTEM\ADO\msado15.dll" no_namespace rename("EOF","adoEOF")  //有些数据库可能安装在D盘,路径要自己修改
  • step2:初始化COM组件
  1. 在MFC中可以用AfxOleInit();
  2. 非MFC环境中用:
    CoInitialize(NULL);
    CoUnInitialize();
 1 CTestAdoApp theApp;//创建COM组件,退出COM组件
 2 /////////////////////////////////////////////////////////////////////////////
 3 // CTestAdoApp initialization
 4 
 5 BOOL CTestAdoApp::InitInstance()
 6 {
 7     AfxEnableControlContainer();
 8     CoInitialize(NULL); //第二步 单线程方式创建COM组件
 9         。。。
10 }
11 ...
12 int CTestAdoApp::ExitInstance() 
13 {
14     // TODO: Add your specialized code here and/or call the base class
15     CoUninitialize();//最后一步 ADO COM 释放
16     return CWinApp::ExitInstance();
17 }
/////////////////////////////////
   if ( !AfxOleInit() ) 
    {
        AfxMessageBox( " OLE fail! ");
        return false;
    }
/////////////////////////////////
  •  step3:初始化数据库连接
 1     //////////////////////////////////////////////////////////////////////////
 2     m_pConn.CreateInstance("ADODB.Connection");
 3     if(m_pConn==NULL)//CoInitialize£¨NULL£©Î´³õʼ»¯
 4     {
 5         TRACE("初始化连接对象失败\n");
 6         return FALSE;
 7     }
 8     HRESULT res=-1;
 9     //////////////////////////////////////////////////////////////////////////
10     CString m_strInEdit;
11     
12     GetPrivateProfileString("SQLLINK","ServerPZ","",m_strInEdit.GetBuffer(MAX_PATH),MAX_PATH,".\\config.ini");
13     m_strInEdit.ReleaseBuffer();
14     if (!m_strInEdit.IsEmpty())
15     {
16         int iLen =m_strInEdit.GetLength();
17         
18         for(int i=0;i<iLen;i++)
19         {
20             m_strInEdit.SetAt(i,m_strInEdit[i]-1);
21         }
22         m_strInEdit.MakeReverse();
23     }
24     //////////////////////////////////////////////////////////////////////////
25     try
26     {
27         CString Sqlstr;
28         //TRACE(m_strInEdit);
29         Sqlstr =m_strInEdit;
30         res = m_pConn->Open((_bstr_t)Sqlstr,"","",0);//´ò¿ª
31         if(res==S_OK)//0
32         {
33             TRACE("打开数据库成功!");
34         }
35         else
36         {
37             TRACE("打开数据库失败!");
38             return FALSE;
39         }
40     }
41     catch(_com_error e)
42     {
43         CString errormessage;
44         errormessage.Format("错误信息:%s",e.ErrorMessage());
45         AfxMessageBox(errormessage);
46         ShellExecute(NULL,"open",".\\sqlLink.exe","config.ini",NULL,SW_SHOW); 
47         return FALSE;
48     }

 

 

  • 另附: ADO Recordset 对象中的updateBatch函数的使用方法

  1.设置 pRecord->CursorLocation = adUseClient;

  2.open方法中设置lockType 为adLockBatchOptimistic  

 1 _RecordsetPtr pRecord;  
 2     pRecord.CreateInstance("ADODB.Recordset");  
 3   
 4     pRecord->CursorLocation = adUseClient;  
 5   
 6     CString strSQL  ;  
 7     strSQL.Append("SELECT * fROM emp ");  
 8       
 9     try  
10     {  
11         pRecord->Open(_bstr_t(strSQL),pConnection.GetInterfacePtr(),adOpenStatic,adLockBatchOptimistic,adCmdText);  
12   
13         CString strValue;  
14         while(!pRecord->AdoEOF)  
15         {  
16             strValue.Format("Test_%d",pRecord->AbsolutePosition);  
17             pRecord->PutCollect("name",_variant_t(strValue));  
18             pRecord->MoveNext();  
19         }  
20   
21         pRecord->UpdateBatch(adAffectAll);  
22         pRecord->Close();  
23     }  
24     catch(_com_error &e)  
25     {  
26         OutputDebugString(e.Description());  
27     }  

 

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------

用DirectShow到了枚举设备,放在程序开始出,没有任何输出结果,查代码发现用的:

    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum,  (void **) &p->pICreateDevEnum);
 返回值居然错误,才恍然大悟,原来是没有初始化COM组件。

加上:

CoInitializeEx(NULL,COINIT_MULTITHREADED|COINIT_SPEED_OVER_MEMORY);

一切正常:)

 

顺便查了下:

CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是 程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
      有哪些方式呢?单线程和多线程。
      CoInitialize 指明以单线程方式创建。
      CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
      创 建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。
      在使用中,使用CoInitialize创建可使对 象直接与线程连接,得到最高的性能。创建多线程对象可以直接接收所有线程的调用,不必像单线程那样需要消息排队,但却需要COM创建线程间汇集代理,这样 访问效率不高。 

注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,一般是在 Dll 中使用 COM 才会需要使用的。

 

 

 

 

 

OleInitialize、CoInitialize、CoInitializeEx和AfxOleInit()区别

  
CoInitialize CoInitializeEx 是用来初始化COM运行环境的。
OleInitialize是初始化Ole的运行环境,Ole是在Com的基础上作的扩展,是ActiveX运行的基础,OleInitialize肯定会调用CoInitialize。
 
CoInitialize、CoInitializeEx都是windows的API,主要是告诉windows以什么方式为程序创建COM对象,原因是程序调用com库函数(除CoGetMalloc和内存分配函数)之前必须初始化com库。
    CoInitialize指明以单线程方式创建。
    CoInitializeEx可以指定COINIT_MULTITHREADED以多线程方式创建。
    创建单线程方式的COM服务器时不用考虑串行化问题,多线程COM服务器就要考虑。
    CoInitialize并不装载com库,这个函数只是用来初始化当前线程使用什么样的套间。当使用这个函数以后,线程就和一个套间建立了对应关系。
    线程的套间模式决定了该线程如何调用com对象,是否需要列集等
    套间是com中用来解决并发调用冲突的很有效的办法
    Before calling any COM functions, a thread needs to call CoInitialize to load the COM infrastructure (and to enter an apartment). Once a thread calls CoInitialize, the thread is free to call COM APIs.
    CoInitializeEx provides the same functionality as CoInitialize and also provides a parameter to explicitly specify the thread's concurrency model. The current implementation of CoInitialize calls CoInitializeEx and specifies the concurrency model as single-thread apartment. Applications developed today should call CoInitializeEx rather than CoInitialize.
    注:新的应用程序应该调用CoInitializeEx而不是CoInitialize,否则就会有必要在之后每个调用Com的线程中调用CoInitialize来初始化出每个线程自己的套间。
 
 AfxOleInit实际上调用了OleInitialize,虽然它在内部也调用了CoInitializeEx,但它只能处理单线程,这是AfxOleInit和CoInitialize主要区别:   
  OleInitialize   calls   CoInitializeEx   internally   to   initialize   the   COM   library   on   the   current   apartment.   Because   OLE   operations   are   not   thread-safe,  OleInitialize   specifies   the   concurrency   model   as   single-thread   apartment.     
  Once   the   concurrency   model   for   an   apartment   is   set,   it   cannot   be  changed.   A   call   to   OleInitialize   on   an   apartment   that   was   previously  initialized   as   multithreaded   will   fail   and   return   RPC_E_CHANGED_MODE.
 
应用:
1. CoInitialize 仅仅初始化Com,支持多线程。也就是说如果多线程调用Com接口,必须在每个线程中都调用CoInitialize。
2. OleInitialize 初始化Com(其实也是调用CoInitializeEx),支持多线程。比CoInitialize多了一下内容:
A) Clipboard
B) Drag and drop
C) Object linking and embedding (OLE)
D) In-place activation
如果不需要这些,用CoInitialize就可以。
3. AfxOleInit是MFC对OleInitialize的封装。貌似不支持多线程,也就是说只能在主进程调用该函数,如果线程需要使用Com必须调用上面的两个来实现初始化。而且MSDN明确标明AfxOleInit不能在MFC的DLL中调用,否则也会造成初始化失败。
4.OleInitialize和OleUninitialize( )成对使用;CoInitialize和CoUninitialize成对使用;CoInitializeEx和CoUninitialize成对使用;AfxOleInit()由MFC自动释放。
 
VC++使用ADO访问ACCESS时,出现_RecordsetPtr Open卡或者_ConnectionPtr Excute卡或者_CommandPtr Excute一直卡住等莫名其妙的情况时,而语法又没有错误时,请确定初始化COM函数。
MFC程序建议使用AfxOleInit()。
posted @ 2016-09-01 10:02  IT-渡子腾  阅读(625)  评论(0)    收藏  举报