modify},
#define end_ado_binding宏的定义也在icrsint.h文件里:
#define end_ado_binding() {0, adempty, 0, 0, 0, 0, 0, 0, 0, false}};\
return rgadobindingentries;}
(2). 绑定
_recordsetptr rs1;
iadorecordbinding *picrs=null;
ccustomrs rs;
......
rs1->queryinterface(__uuidof(iadorecordbinding),
(lpvoid*)&picrs));
picrs->bindtorecordset(&rs);
派生出的类必须通过iadorecordbinding接口才能绑定,调用它的bindtorecordset方法就行了。
(3). rs中的变量即是当前记录字段的值
//set sort and filter condition:
// step 4: manipulate the data
rs1->fields->getitem("au_lname")->properties->getitem("optimize")->value = true;
rs1->sort = "au_lname asc"
rs1->filter = "phone like 阏 5*&"
rs1->movefirst();
while (variant_false == rs1->endoffile)
{
printf("name: %s\t %s\tphone: %s\n",
(rs.lau_fnamestatus == adfldok ? rs.m_szau_fname : ""),
(rs.lau_lnamestatus == adfldok ? rs.m_szau_lname : ""),
(rs.lphonestatus == adfldok ? rs.m_szphone : ""));
if (rs.lphonestatus == adfldok)
strcpy(rs.m_szphone, 蟙");
testhr(picrs->update(&rs)); // add change to the batch
rs1->movenext();
}
rs1->filter = (long) adfilternone;
......
if (picrs) picrs->release();
rs1->close();
pconn->close();
只要字段的状态是adfldok,就可以访问。如果修改了字段,不要忘了先调用picrs的update(注意不是recordset的update),然后才关闭,也不要忘了释放picrs(即picrs->release();)。
(4). 此时还可以用iadorecordbinding接口添加新纪录
if(failed(picrs->addnew(&rs)))
......
11. 访问长数据
在microsoft sql中的长数据包括text、image等这样长类型的数据,作为二进制字节来对待。
可以用field对象的getchunk和appendchunk方法来访问。每次可以读出或写入全部数据的一部分,它会记住上次访问的位置。但是如果中间访问了别的字段后,就又得从头来了。
请看下面的例子:
//写入一张照片到数据库:
variant varchunk;
safearray *psa;
safearraybound rgsabound[1];
//vt_array | vt_ui1
cfile f("h:\\aaa.jpg",cfile::moderead);
byte bval[chunksize+1];
uint uisread=0;
//create a safe array to store the array of bytes
while(1)
{
uisread=f.read(bval,chunksize);
if(uisread==0)break;
rgsabound[0].celements =uisread;
rgsabound[0].llbound = 0;
psa = safearraycreate(vt_ui1,1,rgsabound);
for(long index=0;index<uisread;index++)
{
if(failed(safearrayputelement(psa,&index,&bval[index])))
::messagebox(null,"啊,又出毛病了。","提示",mb_ok | mb_iconwarning);
}
varchunk.vt = vt_array|vt_ui1;
varchunk.parray = psa;
try{
m_precordset->fields->getitem("photo")->appendchunk(varchunk);
}
catch (_com_error &e)
{
cstring str=(char*)e.description();
::messagebox(null,str+"\n又出毛病了。","提示",mb_ok | mb_iconwarning);
}
::variantclear(&varchunk);
::safearraydestroydata( psa);
if(uisread<chunksize)break;
}//while(1)
f.close();
//从数据库读一张照片:
cfile f;
f.open("h:\\bbb.jpg",cfile::modewrite|cfile::modecreate);
long lphotosize = m_precordset->fields->item["photo"]->actualsize;
long lisread=0;
_variant_t varchunk;
byte buf[chunksize];
while(lphotosize>0)
{
lisread=lphotosize>=chunksize? chunksize:lphotosize;
varchunk = m_precordset->fields->
item["photo"]->getchunk(lisread);
for(long index=0;index<lisread;index++)
{
::safearraygetelement(varchunk.parray,&index,buf+index);
}
f.write(buf,lisread);
lphotosize-=lisread;
}//while()
f.close();
12. 使用safearray问题
学会使用safearray也是很重要的,因为在ado编程中经常要用。它的主要目的是用于automation中的数组型参数的传递。因为在网络环境中,数组是不能直接传递的,而必须将其包装成safearray。实质上safearray就是将通常的数组增加一个描述符,说明其维数、长度、边界、元素类型等信息。safearray也并不单独使用,而是将其再包装到variant类型的变量中,然后才作为参数传送出去。在variant的vt成员的值如果包含vt_array|...,那么它所封装的就是一个safearray,它的parray成员即是指向safearray的指针。safearray中元素的类型可以是variant能封装的任何类型,包括variant类型本身。
使用safearray的具体步骤:
方法一:
包装一个safearray:
(1). 定义变量,如:
variant varchunk;
safearray *psa;
safearraybound rgsabound[1];
(2). 创建safearray描述符:
uisread=f.read(bval,chunksize);//read array from a file.