设为首页 加入收藏

TOP

Visual C++ ADO数据库编程入门(四)
2012-11-04 15:12:13 来源: 作者: 【 】 浏览:1436
Tags:Visual ADO 数据库 编程 入门
  7、删除记录

  调用Recordset的Delete方法就行了,删除的是当前记录。要了解Delete的其它用法请查阅参考文献。

try{
m_pRecordset->MoveFirst();
while(m_pRecordset->adoEOF==VARIANT_FALSE)
{
CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem
(_variant_t("姓名"))->Value);
if(::MessageBox(NULL,"姓名="+sName+"\n删除她吗?",
"提示",MB_YESNO │ MB_ICONWARNING)==IDYES)
{
m_pRecordset->Delete(adAffectCurrent);
m_pRecordset->Update();
}
m_pRecordset->MoveNext();
}
}//try
catch (_com_error &e)
{
::MessageBox(NULL,"又出毛病了。","提示",MB_OK │ MB_ICONWARNING);
}

  8、使用带参数的命令

  Command对象所代表的就是一个Provider能够理解的命令,如SQL语句等。使用Command对象的关键就是把表示命令的语句设置到CommandText属性中,然后调用Command对象的Execute方法就行了。一般情况下在命令中无需使用参数,但有时使用参数,可以增加其灵活性和效率。

  (1). 建立连接、命令对象和记录集对象

  本例中表示命令的语句就是一个SQL语句(SELECT语句)。SELECT语句中的问号 就代表参数,如果要多个参数,就多放几个问号,每个问号代表一个参数。

_ConnectionPtr Conn1;
_CommandPtr Cmd1;
ParametersPtr *Params1 = NULL; // Not an instance of a smart pointer.
_ParameterPtr Param1;
_RecordsetPtr Rs1;

try
{
// Create Connection Object (1.5 Version)
Conn1.CreateInstance( __uuidof( Connection ) );
Conn1->ConnectionString = bstrConnect;
Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );
// Create Command Object
Cmd1.CreateInstance( __uuidof( Command ) );
Cmd1->ActiveConnection = Conn1;
Cmd1->CommandText = _bstr_t("SELECT * FROM mytable WHERE age< ");
}//try

  要注意命令对象必须与连接对象关联起来才能起作用,本例中将命令对象的ActiveConnection属性设置为连接对象的指针,即为此目的:

Cmd1->ActiveConnection = Conn1;

  (2). 创建参数对象,并给参数赋值

// Create Parameter Object
Param1 = Cmd1->CreateParameter( _bstr_t(bstrEmpty),
adInteger,
adParamInput,
-1,
_variant_t( (long) 5) );
Param1->Value = _variant_t( (long) 5 );
Cmd1->Parameters->Append( Param1 );

  用命令对象的方法来创建一个参数对象,其中的长度参数(第三个)如果是固定长度的类型,就填-1,如果是字符串等可变长度的就填其实际长度。Parameters是命令对象的一个容器,它的Append方法就是把创建的参数对象追加到该容器里。Append进去的参数按先后顺序与SQL语句中的问号从左至右一一对应。

  (3). 执行命令打开记录集

// Open Recordset Object
Rs1 = Cmd1->Execute( &vtEmpty, &vtEmpty2, adCmdText );

  但要注意,用Command和Connection对象的Execute方法得到的Recordset是只读的。因为在打开Recordset之前,我们无法设置它的LockType属性(其默认值为只读)。而在打开之后设置LockType不起作用。

  我发现用上述方法得到记录集Rs1后,不但Rs1中的记录无法修改,即使直接用SQL语句修改同一表中任何记录都不行。

  要想能修改数据,还是要用Recordset自己的Open方法才行,如:

try{
m_pRecordset->Open((IDispatch *) Cmd1, vtMissing,
adOpenStatic, adLockOptimistic, adCmdUnspecified);
}
catch (_com_error &e)
{
::MessageBox(NULL,"mytable表不存在。","提示",MB_OK │ MB_ICONWARNING);
}

  Recordset对象的Open方法真是太好了,其第一个参数可以是SQL语句、表名字、命令对象指针等等。

  9、响应ADO的通知事件

  通知事件就是当某个特定事件发生时,由Provider通知客户程序,换句话说,就是由Provider调用客户程序中的一个特定的方法(即事件的处理函数)。所以为了响应一个事件,最关键的就是要实现事件的处理函数。

  (1). 从ConnectionEventsVt接口派生出一个类

  为了响应_Connection的通知事件,应该从ConnectionEventsVt接口派生出一个类:

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);
......
};

   (2). 实现每一个事件的处理函数(凡是带raw_前缀的方法都把它实现了):

STDMETHODIMP CConnEvent::raw_InfoMessage(
struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection)
{
*adStatus = adStatusUnwantedEvent;
return S_OK;
};

  有些方法虽然你并不需要,但也必须实现它,只需简单地返回一个S_OK即可。但如果要避免经常被调用,还应在其中将adStatus参数设置为adStatusUnwantedEvent,则在本次调用后,以后就不会被调用了。
另外还必须实现QueryInterface, AddRef, 和Release三个方法:

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;
}

  (3). 开始响应通知事件

// Start using the Connection events
IConnectionPointContainer *pCPC = NULL;
IConnectionPoint *pCP = NULL;

hr = pConn.CreateInstance(__uuidof(Connection));
if (FAILED(hr)) return;

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 rc;
hr = pCP->Advise(pUnk, &dwConnEvt);
pCP->Release();
if (FAILED(hr)) return;

pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified);

  也就是说在连接(Open)之前就做这些事。

  (4). 停止响应通知事件

pConn->Close();
// Stop 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 rc;
hr = pCP->Unadvise( dwConnEvt );
pCP->Release();
if (FAILED(hr)) return;

  在连接关闭之后做这件事。

首页 上一页 1 2 3 4 5 6 7 下一页 尾页 4/8/8
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇ADO与ODBC的区别 下一篇VC实现Access2000文件密码操作技巧

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: