ADO 事件模型范例 (VC++)

转载 2007年10月10日 15:36:00

对实例化 ADO 事件模型的方式进行常规说明。下面是一个在由 #import 伪指令创建的环境中实例化事件模型的特定范例。

常规说明中使用 adoint.h 作为方法声明的引用。但是由于使用 #import 伪指令,因此常规说明中的一些细节需要稍微做些更改。

  • #import 伪指令将 typedef、方法声明数据类型和组合键分解为其基本格式。
  • 所有必须覆盖的纯虚拟方法都被加上前缀“raw_”。

某些代码只反映编码样式。

  • Advise 方法使用的指向 IUnknown 的指针是通过 QueryInterface 调用显式获取的。
  • 不需要在类定义中对析构函数进行显式编码。
  • 用户可能需要使 QueryInterface、AddRef 和 Release 的编码更加可靠。
  • __uuidof() 伪指令的用法可扩展用于获取接口 ID。

最后,该范例还包含某些实用代码。

  • 该范例被编写为控制台应用程序。
  • 应在注释“// Do some work”下插入用户自己的代码。
  • 默认情况下所有事件处理程序不进行任何操作,并且取消进一步的通知。用户应插入应用程序的合适代码,如果需要应允许通知。
// eventmodel.cpp : Defines the entry point for the console application.
//

#import "c:/Program Files/Common Files/System/ADO/msado15.dll" /
   no_namespace rename("EOF", "EndOfFile")
#include <comdef.h>
#include <stdio.h>

//----The Connection events----------------------------------------------

class CConnEvent : public ConnectionEventsVt
{
private:
        ULONG   m_cRef;
    public:
        CConnEvent() { m_cRef = 0; };
        ~CConnEvent() {};


        STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
        STDMETHODIMP_(ULONG) AddRef(void);
        STDMETHODIMP_(ULONG) Release(void);

        STDMETHODIMP raw_InfoMessage( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_BeginTransComplete( 
            LONG TransactionLevel,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
      
    STDMETHODIMP raw_CommitTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_RollbackTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_WillExecute( 
            BSTR *Source,
            CursorTypeEnum *CursorType,
            LockTypeEnum *LockType,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_ExecuteComplete( 
            LONG RecordsAffected,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection);
        
    STDMETHODIMP raw_WillConnect( 
            BSTR *ConnectionString,
            BSTR *UserID,
            BSTR *Password,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_ConnectComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
        
        STDMETHODIMP raw_Disconnect( 
            EventStatusEnum *adStatus,
            struct _Connection *pConnection);
};

//-----The Recordset events----------------------------------------------

class CRstEvent : public RecordsetEventsVt
    {
    private:
        ULONG m_cRef;   
    public:
        CRstEvent() { m_cRef = 0; };
        ~CRstEvent() {};

            STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);
            STDMETHODIMP_(ULONG) AddRef(void);
            STDMETHODIMP_(ULONG) Release(void);

            STDMETHODIMP raw_WillChangeField( 
            LONG cFields,
            VARIANT Fields,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FieldChangeComplete( 
            LONG cFields,
            VARIANT Fields,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillChangeRecord( 
            EventReasonEnum adReason,
            LONG cRecords,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_RecordChangeComplete( 
            EventReasonEnum adReason,
            LONG cRecords,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillChangeRecordset( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_RecordsetChangeComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_WillMove( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_MoveComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_EndOfRecordset( 
            VARIANT_BOOL *fMoreData,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FetchProgress( 
            long Progress,
            long MaxProgress,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
        
        STDMETHODIMP raw_FetchComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset);
};


//-----Implement each connection method----------------------------------

        STDMETHODIMP CConnEvent::raw_InfoMessage( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_BeginTransComplete( 
            LONG TransactionLevel,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_CommitTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_RollbackTransComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
    STDMETHODIMP CConnEvent::raw_WillExecute( 
            BSTR *Source,
            CursorTypeEnum *CursorType,
            LockTypeEnum *LockType,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_ExecuteComplete( 
            LONG RecordsAffected,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Command *pCommand,
            struct _Recordset *pRecordset,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_WillConnect( 
            BSTR *ConnectionString,
            BSTR *UserID,
            BSTR *Password,
            long *Options,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_ConnectComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CConnEvent::raw_Disconnect( 
            EventStatusEnum *adStatus,
            struct _Connection *pConnection)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };


//-----Implement each recordset method-----------------------------------

        STDMETHODIMP CRstEvent::raw_WillChangeField( 
            LONG cFields,
            VARIANT Fields,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FieldChangeComplete( 
            LONG cFields,
            VARIANT Fields,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillChangeRecord( 
            EventReasonEnum adReason,
            LONG cRecords,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_RecordChangeComplete( 
            EventReasonEnum adReason,
            LONG cRecords,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillChangeRecordset( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_RecordsetChangeComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_WillMove( 
            EventReasonEnum adReason,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_MoveComplete( 
            EventReasonEnum adReason,
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_EndOfRecordset( 
            VARIANT_BOOL *fMoreData,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FetchProgress( 
            long Progress,
            long MaxProgress,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };
        
        STDMETHODIMP CRstEvent::raw_FetchComplete( 
            struct Error *pError,
            EventStatusEnum *adStatus,
            struct _Recordset *pRecordset)
            {
            *adStatus = adStatusUnwantedEvent;
            return S_OK;
            };


//-----Implement QueryInterface, AddRef, and Release---------------------

    STDMETHODIMP CRstEvent::QueryInterface(REFIID riid, void ** ppv) 
    {
        *ppv = NULL;
        if (riid == __uuidof(IUnknown) || 
                 riid == __uuidof(RecordsetEventsVt)) *ppv = this;
        if (*ppv == NULL)
            return ResultFromScode(E_NOINTERFACE);
        AddRef();
        return NOERROR;
    }
    STDMETHODIMP_(ULONG) CRstEvent::AddRef(void) { return ++m_cRef; };
    STDMETHODIMP_(ULONG) CRstEvent::Release()   
                                        { 
                                        if (0 != --m_cRef) return m_cRef;
                                        delete this;
                                        return 0;
                                        }

    STDMETHODIMP CConnEvent::QueryInterface(REFIID riid, void ** ppv) 
        
    {
        *ppv = NULL;
        if (riid == __uuidof(IUnknown) || 
             riid == __uuidof(ConnectionEventsVt)) *ppv = this;
        if (*ppv == NULL)
            return ResultFromScode(E_NOINTERFACE);
        AddRef();
        return NOERROR;
    }
    STDMETHODIMP_(ULONG) CConnEvent::AddRef() { return ++m_cRef; };
    STDMETHODIMP_(ULONG) CConnEvent::Release()    
                                        { 
                                        if (0 != --m_cRef) return m_cRef;
                                        delete this;
                                        return 0;
                                        }

//-----Write your main block of code-------------------------------------

int main(int argc, char* argv[])
{
    HRESULT hr;
    DWORD   dwConnEvt;
    DWORD   dwRstEvt;
    IConnectionPointContainer   *pCPC = NULL;
    IConnectionPoint         *pCP = NULL;
    IUnknown               *pUnk = NULL;
    CRstEvent               *pRstEvent = NULL;
    CConnEvent               *pConnEvent= NULL;
    int                     rc = 0;
    _RecordsetPtr            pRst; 
    _ConnectionPtr            pConn;

    ::CoInitialize(NULL);
    
    hr = pConn.CreateInstance(__uuidof(Connection));
    if (FAILED(hr)) return rc;
    
    hr = pRst.CreateInstance(__uuidof(Recordset));
    if (FAILED(hr)) return rc;

    // Start using the Connection events

    hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **)&pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;

    pConnEvent = new CConnEvent();
    hr = pConnEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
    if (FAILED(hr)) return rc;
    hr = pCP->Advise(pUnk, &dwConnEvt);
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Start using the Recordset events

    hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **)&pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;

    pRstEvent = new CRstEvent();
    hr = pRstEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);
    if (FAILED(hr)) return rc;
    hr = pCP->Advise(pUnk, &dwRstEvt);
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Do some work

    pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified);
    pRst->Open("SELECT * FROM authors", (IDispatch *) pConn, 
            adOpenStatic, adLockReadOnly, adCmdText);
    pRst->MoveFirst();
    while (pRst->EndOfFile == FALSE)
    {
        wprintf(L"Name = '%s'/n", (wchar_t*) 
            ((_bstr_t) pRst->Fields->GetItem("au_lname")->Value));
        pRst->MoveNext();
    }

    pRst->Close();
    pConn->Close();

    // Stop using the Connection events

    hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **) &pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;
    hr = pCP->Unadvise( dwConnEvt );
    pCP->Release();
    if (FAILED(hr)) return rc;

    // Stop using the Recordset events
    hr = pRst->QueryInterface(__uuidof(IConnectionPointContainer), 
        (void **) &pCPC);
    if (FAILED(hr)) return rc;
    hr = pCPC->FindConnectionPoint(__uuidof(RecordsetEvents), &pCP);
    pCPC->Release();
    if (FAILED(hr)) return rc;
    hr = pCP->Unadvise( dwRstEvt );
    pCP->Release();
    if (FAILED(hr)) return rc;

    CoUninitialize();
    return 1;
}

 

VC++下ADO数据库操作的封装类

一、ADO 对象 对象 说明 Command Command 对象定义了将对数据源执行的指定命令。 Connection ...
  • woshibendangao
  • woshibendangao
  • 2014年01月20日 11:50
  • 1341

VC+ADO+多线程高效、安全的读写数据库

一、问题介绍项目需要实时获取并处理40路相机的现场图像,并将处理结果写入到数据库,采用的方案是使用多线程技术,创建40个工作者线程,每个线程建立一个数据库连接。本文仅将项目中遇到的问题以及解决方法做些...
  • HolaMirai
  • HolaMirai
  • 2016年09月05日 16:31
  • 2320

ADO对象模型总结

ADO 简介 ActiveX data Object (取代 dao 和rdo) 通过 OLE DB 实现不同类型数据源的访问  有三种类型  数据提供者:将特殊数据转化成关系型数据表  数据消费者 ...
  • cJune
  • cJune
  • 2016年05月08日 19:26
  • 1712

VC使用ADO连接SQLServer数据库(精简实用版)

VC使用ADO连接SQLServer数据库 分类: 开发路上的点点滴滴2012-05-18 18:32 946人阅读 评论(0) 收藏 举报 sqlservermicrosoft数...
  • foreverhuylee
  • foreverhuylee
  • 2014年06月28日 14:46
  • 1779

分享关于VC 使用ADO数据库使用的方法封装类

ADO访问数据库的
  • YinLeNan
  • YinLeNan
  • 2014年07月27日 14:43
  • 638

ADO对象模型访问数据库

这几天被数据库这些东西给整头疼了,这些代码,不确切的说是“单词”,认识的真没有几个,OK,先看下面的代码,等一下围绕 ADO对象模型访问数据库分享点东西。 Option Explicit Di...
  • u010282984
  • u010282984
  • 2016年01月31日 18:52
  • 585

VC用ADO访问数据库

VC用ADO访问数据库全攻略,介绍了VC用ADO来访问数据库的各个对象及各方法,很经典,也很实用,很值得一看。  正文  一、ADO概述  ADO是Microsoft为最新和最强大的数据访问...
  • worldy
  • worldy
  • 2013年09月21日 11:18
  • 4546

VC++实现批量大容量快速插入SqlServer数据库

1. 概述 使用c++访问数据库的方法很多,由于我访问的是sqlserver数据库,于是上MSDN查了一下有哪些访问技术,主要有以下几种: ODBC  OLEDBADO ADO是OLEDB的封装...
  • winnyrain
  • winnyrain
  • 2017年06月30日 16:09
  • 639

在vc中自定义事件扩展控件功能

当MFC所提供的控件不能满足我们的要求时,我们需要为控件进行功能扩展,根据需求自定义控件的事件。 本文以一个扩展按钮的鼠标按下和鼠标松开的事件为例,其它控件事件扩展可遵照该例。提供源代码,在...
  • xiaoyafang123
  • xiaoyafang123
  • 2016年08月09日 14:11
  • 786

如何使用VC++对ADO的扩展

如何使用VC++对ADO的扩展 IADORecordBinding接口 VC++对ADO的扩展联系或绑定了一个Recordset对象的各个字段到C/C++变量。当被绑定的Recordset的当...
  • worldy
  • worldy
  • 2013年10月15日 13:28
  • 564
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:ADO 事件模型范例 (VC++)
举报原因:
原因补充:

(最多只允许输入30个字)