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)
{