| |
Visual C++ ADO数据库编程入门 |
|
时间: 2004-08-09 来自:CSDN |
 |
|
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; | 在连接关闭之后做这件事。
|
|
|
|
|
|
|
|