📄 ado数据库编程入门.htm
字号:
......<br>
m_pRecordset->Update();<br>
m_pRecordset->MoveNext(); <br>
}<br>
}//try</font><font face="Arial"><font face="Arial" size=2><br>
<br>
改变了Value属性的值,即改变了字段的值。<br>
<br>
方法二:<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
m_pRecordset->Fields->GetItem(_variant_t("姓名"))->PutValue(_bstr_t("赵薇"));</font><font face="Arial"><font face="Arial" size=2><br>
<br>
方法三:就是用定义绑定类的方法(详见后面的介绍)。<br>
<br>
6、添加记录<br>
新记录添加成功后,即自动成为当前记录。AddNew方法有两种形式,一个含有参数,而另一个则不带参数。<br>
方法一(不带参数):<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
// Add new record into this table:<br>
try<br>
{<br>
if(!m_pRecordset->Supports(adAddNew)) return;<br>
m_pRecordset->AddNew(); <br>
m_pRecordset->Fields->GetItem(_variant_t("姓名"))->Value=_bstr_t("赵薇");<br>
m_pRecordset->Fields->GetItem(_variant_t("性别"))->Value=_bstr_t("女");<br>
m_pRecordset->Fields->GetItem(_variant_t("age"))->Value=_variant_t((short)20);<br>
m_pRecordset->Fields->GetItem(_variant_t("marry"))->Value=_bstr_t("未婚");<br>
m_pRecordset->Update(); <br>
}//try<br>
catch (_com_error &e)<br>
{<br>
::MessageBox(NULL, "又出毛病了。","提示",MB_OK | MB_ICONWARNING);<br>
}</font><font face="Arial"><font face="Arial" size=2><br>
<br>
这种方法弄完了还要调用Update()。<br>
方法二(带参数):<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
_variant_t varName[4],narValue[4];<br>
varName[0] = L"姓名";<br>
varName[1] = L"性别";<br>
varName[2] = L"age";<br>
varName[3] = L"marry";<br>
narValue[0]=_bstr_t("赵薇");<br>
narValue[1]=_bstr_t("女");<br>
narValue[2]=_variant_t((short)20);<br>
narValue[3]=_bstr_t("未婚");<br>
const int nCrit = sizeof varName / sizeof varName[0];<br>
<br>
// Create SafeArray Bounds and initialize the array<br>
SAFEARRAYBOUND rgsaName[1],rgsaValue[1];<br>
rgsaName[0].lLbound = 0; <br>
rgsaName[0].cElements = nCrit;<br>
SAFEARRAY *psaName = SafeArrayCreate( VT_VARIANT, 1, rgsaName );<br>
rgsaValue[0].lLbound = 0;<br>
rgsaValue[0].cElements = nCrit;<br>
SAFEARRAY *psaValue = SafeArrayCreate( VT_VARIANT, 1, rgsaValue );<br>
<br>
// Set the values for each element of the array<br>
HRESULT hr1=S_OK.hr2=S_OK;<br>
<br>
for( long i = 0 ; i < nCrit && SUCCEEDED( hr1 ) && SUCCEEDED( hr2
);i++) <br>
{ <br>
hr1=SafeArrayPutElement(psaName, &i,&varName[i]);<br>
hr2=SafeArrayPutElement(psaValue, &i,&narValue[i]);<br>
}<br>
<br>
// Initialize and fill the SafeArray<br>
VARIANT vsaName,vsaValue; <br>
vsaName.vt = VT_VARIANT | VT_ARRAY;<br>
vsaValue.vt = VT_VARIANT | VT_ARRAY;<br>
V_ARRAY(&vsaName) = psaName;//&vsaName->parray=psaName;<br>
//see definition in oleauto.h file.<br>
V_ARRAY(&vsaValue) = psaValue;<br>
<br>
// Add a new record:<br>
m_pRecordset->AddNew(vsaName,vsaValue);</font><font face="Arial"><font face="Arial" size=2><br>
<br>
这种方法不需要调用Update,因为添加后,ADO会自动调用它。此方法主要是使用SafeArray挺麻烦。<br>
<br>
方法三:就是用定义绑定类的方法(详见后面的介绍)。<br>
<br>
7、删除记录<br>
调用Recordset的Delete方法就行了,删除的是当前记录。要了解Delete的其它用法请查阅参考文献。<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
try<br>
{<br>
m_pRecordset->MoveFirst(); <br>
while(m_pRecordset->adoEOF==VARIANT_FALSE) <br>
{<br>
CString sName=(char*)(_bstr_t)(m_pRecordset->Fields->GetItem(_variant_t("姓名"))->Value);<br>
if(::MessageBox(NULL,"姓名="+sName+"\n删除她吗?", "提示",MB_YESNO | MB_ICONWARNING)==IDYES)<br>
{<br>
m_pRecordset->Delete(adAffectCurrent); <br>
m_pRecordset->Update();<br>
}<br>
m_pRecordset->MoveNext(); <br>
}<br>
}//try<br>
catch (_com_error &e)<br>
{<br>
::MessageBox(NULL,"又出毛病了。","提示",MB_OK | MB_ICONWARNING);<br>
}<br>
</font>
<font face="Arial">
<font face="Arial" size=2>
<br>
8、使用带参数的命令<br>
Command对象所代表的就是一个Provider能够理解的命令,如SQL语句等。使用Command对象的关键就是把表示命令的语句设置到CommandText属性中,然后调用Command对象的Execute方法就行了。一般情况下在命令中无需使用参数,但有时使用参数,可以增加其灵活性和效率。<br>
<br>
(1). 建立连接、命令对象和记录集对象<br>
本例中表示命令的语句就是一个SQL语句(SELECT语句)。SELECT语句中的问号?就代表参数,如果要多个参数,就多放几个问号,每个问号代表一个参数。<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
_ConnectionPtr Conn1;<br>
_CommandPtr Cmd1;<br>
ParametersPtr *Params1 = NULL; // Not an instance of a smart pointer.<br>
_ParameterPtr Param1;<br>
_RecordsetPtr Rs1;<br>
<br>
try<br>
{<br>
// Create Connection Object (1.5 Version)<br>
Conn1.CreateInstance( __uuidof( Connection ) );<br>
Conn1->ConnectionString = bstrConnect;<br>
Conn1->Open( bstrEmpty, bstrEmpty, bstrEmpty, -1 );<br>
<br>
// Create Command Object<br>
Cmd1.CreateInstance( __uuidof( Command ) );<br>
Cmd1->ActiveConnection = Conn1;<br>
Cmd1->CommandText = _bstr_t("SELECT * FROM mytable WHERE age< ?");<br>
}//try</font><font face="Arial"><font face="Arial" size=2><br>
<br>
要注意命令对象必须与连接对象关联起来才能起作用,本例中将命令对象的ActiveConnection属性设置为连接对象的指针,即为此目的:<br>
<br>
<font color="#99CCFF">Cmd1->ActiveConnection = Conn1;</font><br>
<br>
(2). 创建参数对象,并给参数赋值<br>
<br>
</font>
</font>
<font color="#99CCFF" face="宋体" size="2">// Create Parameter Object<br>
Param1 = Cmd1->CreateParameter( _bstr_t(bstrEmpty),
adInteger,
adParamInput,
-1,
_variant_t((long) 5) );<br>
Param1->Value = _variant_t( (long) 5 );<br>
Cmd1->Parameters->Append( Param1 );</font><font face="Arial"><font face="Arial" size=2><br>
<br>
用命令对象的方法来创建一个参数对象,其中的长度参数(第三个)如果是固定长度的类型,就填-1,如果是字符串等可变长度的就填其实际长度。Parameters是命令对象的一个容器,它的Append方法就是把创建的参数对象追加到该容器里。Append进去的参数按先后顺序与SQL语句中的问号从左至右一一对应。<br>
<br>
(3). 执行命令打开记录集<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
// Open Recordset Object<br>
Rs1 = Cmd1->Execute( &vtEmpty, &vtEmpty2, adCmdText );</font><font face="Arial"><font face="Arial" size=2><br>
<br>
但要注意,用Command和Connection对象的Execute方法得到的Recordset是只读的。因为在打开Recordset之前,我们无法设置它的LockType属性(其默认值为只读)。而在打开之后设置LockType不起作用。<br>
我发现用上述方法得到记录集Rs1后,不但Rs1中的记录无法修改,即使直接用SQL语句修改同一表中任何记录都不行。<br>
要想能修改数据,还是要用Recordset自己的Open方法才行,如:<br>
<br>
</font>
</font>
<font color="#99CCFF" face="宋体" size="2">try{<br>
m_pRecordset->Open((IDispatch *) Cmd1, vtMissing, adOpenStatic, adLockOptimistic, adCmdUnspecified);<br>
}<br>
catch (_com_error &e)<br>
{<br>
::MessageBox(NULL,"mytable表不存在。","提示",MB_OK | MB_ICONWARNING);<br>
}</font><font face="Arial"><font face="Arial" size=2><br>
<br>
Recordset对象的Open方法真是太好了,其第一个参数可以是SQL语句、表名字、命令对象指针等等。<br>
<br>
9、响应ADO的通知事件<br>
通知事件就是当某个特定事件发生时,由Provider通知客户程序,换句话说,就是由Provider调用客户程序中的一个特定的方法(即事件的处理函数)。所以为了响应一个事件,最关键的就是要实现事件的处理函数。<br>
<br>
(1). 从ConnectionEventsVt接口派生出一个类<br>
为了响应_Connection的通知事件,应该从ConnectionEventsVt接口派生出一个类:<br>
<br>
</font>
</font>
<font face="宋体" size="2" color="#99CCFF">
class CConnEvent : public ConnectionEventsVt<br>
{<br>
private:<br>
ULONG m_cRef;<br>
<br>
public:<br>
CConnEvent() { m_cRef = 0; };<br>
~CConnEvent() {};<br>
<br>
STDMETHODIMP QueryInterface(REFIID riid, void ** ppv);<br>
STDMETHODIMP_(ULONG) AddRef(void);<br>
STDMETHODIMP_(ULONG) Release(void);<br>
STDMETHODIMP raw_InfoMessage(
struct Error *pError,
EventStatusEnum *adStatus,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -