📄 ado数据库编程入门.htm
字号:
struct _Connection *pConnection);<br>
STDMETHODIMP raw_BeginTransComplete(
LONG TransactionLevel,
struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection);<br>
......<br>
};</font><font face="Arial"><font face="Arial" size=2><br>
<br>
(2). 实现每一个事件的处理函数(凡是带raw_前缀的方法都把它实现了):<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
STDMETHODIMP CConnEvent::raw_InfoMessage(
struct Error *pError,
EventStatusEnum *adStatus,
struct _Connection *pConnection)<br>
{<br>
*adStatus = adStatusUnwantedEvent;<br>
return S_OK;<br>
};</font><font face="Arial"><font face="Arial" size=2><br>
<br>
有些方法虽然你并不需要,但也必须实现它,只需简单地返回一个S_OK即可。但如果要避免经常被调用,还应在其中将adStatus参数设置为adStatusUnwantedEvent,则在本次调用后,以后就不会被调用了。<br>
另外还必须实现QueryInterface, AddRef, 和Release三个方法: <br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
STDMETHODIMP CConnEvent::QueryInterface(REFIID riid, void ** ppv)<br>
{<br>
*ppv = NULL;<br>
if (riid == __uuidof(IUnknown) ||
riid == __uuidof(ConnectionEventsVt))<br>
*ppv = this;<br>
<br>
if (*ppv == NULL)<br>
return ResultFromScode(E_NOINTERFACE);<br>
<br>
AddRef();<br>
return NOERROR;<br>
}<br>
<br>
STDMETHODIMP_(ULONG) CConnEvent::AddRef() { return ++m_cRef; };<br>
<br>
STDMETHODIMP_(ULONG) CConnEvent::Release()<br>
{<br>
if (0 != --m_cRef)<br>
return m_cRef;<br>
<br>
delete this;<br>
return 0;<br>
}</font><font face="Arial"><font face="Arial" size=2><br>
<br>
(3). 开始响应通知事件<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
// Start using the Connection events<br>
IConnectionPointContainer *pCPC = NULL;<br>
IConnectionPoint *pCP = NULL;<br>
hr = pConn.CreateInstance(__uuidof(Connection));<br>
if (FAILED(hr))<br>
return;<br>
<br>
hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer),
(void **)&pCPC);<br>
if (FAILED(hr))<br>
return;<br>
<br>
hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);<br>
pCPC->Release();<br>
if (FAILED(hr))<br>
return;<br>
<br>
pConnEvent = new CConnEvent();<br>
hr = pConnEvent->QueryInterface(__uuidof(IUnknown), (void **) &pUnk);<br>
if (FAILED(hr))<br>
return rc;<br>
<br>
hr = pCP->Advise(pUnk, &dwConnEvt);<br>
pCP->Release();<br>
if (FAILED(hr))<br>
return;<br>
<br>
pConn->Open("dsn=Pubs;", "sa", "", adConnectUnspecified);</font><font face="Arial"><font face="Arial" size=2><br>
<br>
也就是说在连接(Open)之前就做这些事。<br>
<br>
(4). 停止响应通知事件<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
pConn->Close();<br>
// Stop using the Connection events<br>
hr = pConn->QueryInterface(__uuidof(IConnectionPointContainer),
(void **) &pCPC);<br>
if (FAILED(hr))<br>
return;<br>
<br>
hr = pCPC->FindConnectionPoint(__uuidof(ConnectionEvents), &pCP);<br>
pCPC->Release();<br>
if (FAILED(hr))<br>
return rc;<br>
<br>
hr = pCP->Unadvise( dwConnEvt );<br>
pCP->Release();<br>
if (FAILED(hr))<br>
return;</font><font face="Arial"><font face="Arial" size=2><br>
<br>
在连接关闭之后做这件事。<br>
<br>
10、邦定数据<br>
定义一个绑定类,将其成员变量绑定到一个指定的记录集,以方便于访问记录集的字段值。<br>
<br>
(1). 从CADORecordBinding派生出一个类:<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
class CCustomRs : public CADORecordBinding<br>
{<br>
BEGIN_ADO_BINDING(CCustomRs)<br>
ADO_VARIABLE_LENGTH_ENTRY2(3, adVarChar, m_szau_fname,
sizeof(m_szau_fname), lau_fnameStatus, false)<br>
ADO_VARIABLE_LENGTH_ENTRY2(2, adVarChar, m_szau_lname,
sizeof(m_szau_lname), lau_lnameStatus, false)<br>
ADO_VARIABLE_LENGTH_ENTRY2(4, adVarChar, m_szphone,
sizeof(m_szphone), lphoneStatus, true)<br>
END_ADO_BINDING()<br>
<br>
public:<br>
CHAR m_szau_fname[22];<br>
ULONG lau_fnameStatus;<br>
CHAR m_szau_lname[42];<br>
ULONG lau_lnameStatus;<br>
CHAR m_szphone[14];<br>
ULONG lphoneStatus;<br>
};</font><font face="Arial"><font face="Arial" size=2><br>
<br>
其中将要绑定的字段与变量名用BEGIN_ADO_BINDING宏关联起来。每个字段对应于两个变量,一个存放字段的值,另一个存放字段的状态。字段用从1开始的序号表示,如1,2,3等等。<br>
特别要注意的是:如果要绑定的字段是字符串类型,则对应的字符数组的元素个数一定要比字段长度大2(比如m_szau_fname[22],其绑定的字段au_fname的长度实际是20),不这样绑定就会失败。我分析多出的2可能是为了存放字符串结尾的空字符null和BSTR字符串开头的一个字(表示BSTR的长度)。这个问题对于初学者来说可能是一个意想不到的问题。<br>
CADORecordBinding类的定义在icrsint.h文件里,内容是:<br>
<br>
</font></font>
</font>
<font face="宋体" size="2" color="#99CCFF">class CADORecordBinding<br>
{<br>
public:<br>
STDMETHOD_(const ADO_BINDING_ENTRY*, GetADOBindingEntries) (VOID)
PURE;<br>
};<br>
<br>
</font><font face="Arial" size="2">BEGIN_ADO_BINDING宏的定义也在icrsint.h文件里,内容是:</font><font face="宋体" size="2" color="#99CCFF"><br>
<br>
#define BEGIN_ADO_BINDING(cls) public: \<br>
typedef cls ADORowClass; \<br>
const ADO_BINDING_ENTRY* STDMETHODCALLTYPE GetADOBindingEntries() { \<br>
static const ADO_BINDING_ENTRY rgADOBindingEntries[] = {<br>
ADO_VARIABLE_LENGTH_ENTRY2宏的定义也在icrsint.h文件里:<br>
#define ADO_VARIABLE_LENGTH_ENTRY2(Ordinal, DataType, Buffer, Size,
Status, Modify)\<br>
{Ordinal, \<br>
DataType, \<br>
0, \<br>
0, \<br>
Size, \<br>
offsetof(ADORowClass, Buffer), \<br>
offsetof(ADORowClass, Status), \<br>
0, \<br>
classoffset(CADORecordBinding, ADORowClass), \<br>
Modify},<br>
#define END_ADO_BINDING宏的定义也在icrsint.h文件里:<br>
#define END_ADO_BINDING() {0, adEmpty, 0, 0, 0, 0, 0, 0, 0, FALSE}};\<br>
return rgADOBindingEntries;}</font><font face="Arial"><font face="Arial" size="2"><br>
<br>
(2). 绑定<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
_RecordsetPtr Rs1;<br>
IADORecordBinding *picRs=NULL;<br>
CCustomRs rs;<br>
......<br>
Rs1->QueryInterface(__uuidof(IADORecordBinding),
(LPVOID*)&picRs));<br>
picRs->BindToRecordset(&rs);</font><font face="Arial"><font face="Arial" size="2"><br>
<br>
派生出的类必须通过IADORecordBinding接口才能绑定,调用它的BindToRecordset方法就行了。<br>
<br>
(3). rs中的变量即是当前记录字段的值<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
//Set sort and filter condition:<br>
// Step 4: Manipulate the data<br>
Rs1->Fields->GetItem("au_lname")->Properties->GetItem("Optimize")->Value
= true;<br>
Rs1->Sort = "au_lname ASC";<br>
Rs1->Filter = "phone LIKE '415 5*'";<br>
Rs1->MoveFirst();<br>
while (VARIANT_FALSE == Rs1->EndOfFile)<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -