- 在线时间
- 0 小时
- 最后登录
- 2007-11-12
- 注册时间
- 2004-12-24
- 听众数
- 2
- 收听数
- 0
- 能力
- 0 分
- 体力
- 2467 点
- 威望
- 0 点
- 阅读权限
- 50
- 积分
- 882
- 相册
- 0
- 日志
- 0
- 记录
- 0
- 帖子
- 205
- 主题
- 206
- 精华
- 2
- 分享
- 0
- 好友
- 0
升级   70.5% 该用户从未签到
 |
1. 生成应用程序框架并初始化OLE/COM库环境 ' y2 l' l# }$ u2 c5 b
- F0 W+ \+ b0 G% K. B9 b: w p
创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。) e1 O6 P% G6 E+ g# S
本例为: ! C4 B2 B" S y p' O
9 k7 h* N4 j" I7 C7 ], U: L; f
BOOL CAdotestDlg::OnInitDialog()' A: G) @5 j7 h& x2 f0 S; C
{
4 U% m3 H. H; r ::CoInitialize(NULL); //初始化OLE/COM库环境
' O$ j9 n @! C }
/ H& B. }# m: ~6 Z' `, U9 c- n3 R5 C! E/ N& F9 B2 A) H0 q! `& ^# x
程序最后要调用 ::CoUninitialize();//释放程序占用的COM 资源。9 Q8 z6 a& A3 P+ A0 B: D
/ ^- D+ c' J( r: Z( F
另外:+ u4 K- ~& q$ X
0 R1 L" i* u6 D
m_pRecordset->Close(); 注意!!!不要多次关闭!!!!!!!!!!!!1 d9 a7 {& v2 `( v% d! j
m_pConnection->Close();6 [- P9 R, d- p# S% o# s% V
m_pRecordset = NULL;, M4 `2 A9 Z5 [( m1 P0 a, ]
m_pConnection = NULL; ( d8 C$ \" G0 F/ |* ~% t0 e$ j; x0 {- t
2. 引入ADO库文件 ) v2 |/ J% i3 o; T$ g
3 a) ]% _# u. u5 I/ c' {5 l 使用ADO前必须在工程的stdafx.h文件最后用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下: w0 g% N/ h# [7 t$ v
#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
5 [( g5 |% k& Q. ^2 C+ r ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。 " ]0 s) [# e( p5 |. B! D
程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
. J6 p4 q$ t& ?" a, Y
9 p i9 J; L& k" f4 Y 3.利用智能指针进行数据库操作 2 o2 \3 _/ l9 e/ Y9 t
3 x- W- m( A6 J5 t1 \
在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。
& ~, x9 g. z, R) @6 ^- j3 s2 i, s1 E, P' T5 G/ [/ K
class CAdotestDlg : public CDialog, x, I9 A! U7 B' L, `( j, {/ P/ V
{0 c% d1 S! x, _
_ConnectionPtr m_pConnection;4 {5 O9 }" @1 m# q9 t6 P
_RecordsetPtr m_pRecordset;
: ~0 V X; O9 W ClistCtrl m_List;
7 M( _4 f2 i: [# _ P ......7 c! R) r1 r) V. G; z2 f1 E
} + F# n* L3 U1 i6 c7 }8 H
w3 v" e, p, x' w, c& J ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。 o B6 l) k! R% X: E7 Y% A2 u# g
: \) w; X& Q. o$ O. e
_ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
8 e- Z3 I# r9 P( R. ?/ j _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。 _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。
) Y" i6 n2 }3 I* ~ V! }
* Q8 a7 ]/ \ ]3 y, w0 a 在使用ADO程序的事件响应中OnButton1加入以下代码:
4 u; P2 m7 Y" U' [, p& C) |2 S# r* H- B" H6 T9 }+ W
void CAdotestDlg::OnButton1() 8 D2 s4 u1 S6 E+ p) x
{) D- A0 t* T# Z- f/ U. X. Y; {
m_List.ResetContent();
. r: ]9 a* @: l4 @; w6 M% M( rm_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针
5 F# h& e2 X) z3 lm_pRecordset.CreateInstance(_uuidof(Recordset));//初始化Recordset指针& b3 B( U6 |* x0 E. i& W5 H
try
4 @& B' v4 H9 w8 ~# c/ P, \( X( @{# _" Z4 u# g9 }& N
m_pConnection->Open("DSN=ADOTest","","",0); //连接叫作ADOTest的ODBC数据源
% q, w. m: S, [! \! ?9 A" z //注意:这是连接不需要用户ID或密码的open 函数
5 o, j, i, y. Z- N, X // 否则形式为 ->Open("DSN=test;uid=sa;pwd=123;","","",0);
8 c, |+ w4 M) Z# d( W2 ^; d( f
; N% W; }/ ~( ]8 L // 执行SQL语句得到一个记录集把其指针赋值给m_pRecordset
5 G8 @8 ~, w, M# e3 k CString strSql="select * from middle";& ?. R; o# K; h3 f
BSTR bstrSQL = strSql.AllocSysString(); + n& {/ ~+ D- p! `! \, Y
m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);
9 l# H4 }- y% W& O6 y0 b! c6 @ //adOpenDynamic:动态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
) [# I9 a3 t: ~# N$ K+ |& q8 @, w while(!m_pRecordset->adoEOF)//遍历所有记录
1 ]. P0 K" ^" q { - v+ n3 X% \ }7 j) y
//取纪录字段值方式之一
0 r" ~2 D; y% n/ E( n$ m _variant_t Thevalue; //VARIANT数据类型
% f3 B5 H* ]" q/ ?* L/ y. F Thevalue = m_pRecordset->GetCollect("BIG_NAME");//得到字段BIG_NAME的值( n* e$ [2 Q7 c: x5 J
if(Thevalue.vt!=VT_NULL)
" { S: e7 g: _. M" H m_List.AddString((char*)_bstr_t(Thevalue));) E9 q2 B* C0 P, p
//将该值加入到列表控件中
d* _% o! ~% q) F7 y9 s" D1 }. D
( s; d! g O! M5 h- M1 a //取纪录字段值方式之二; L- F0 t) ~& W; O
// _bstr_t Thevalue1=m_pRecordset->Fields->GetItem("BIG_NAME")->value;
+ z" x3 N6 u/ \# d0 Z // CString temp=Thevalue1.copy();
; F6 N6 C( n" s1 |9 \2 r // m_List.AddString(temp);% z' K8 k1 r( e% m f+ j
//数据类型转换
1 }- l; `0 A! E: D0 a _variant_t vUsername,vBirthday,vID,vOld;5 F6 ~) H' W8 e% A* `. L: `$ D) M$ s
TRACE("id:%d,姓名:%s,年龄:%d,生日:%s\r\n",
1 c0 i( A5 U* c& w2 x& Z% M vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);! V0 u4 o# ?- b7 B9 Q
( o5 T3 z: z, i& I% j# u m_pRecordset->MoveNext();//转到下一条纪录2 |* C4 l, A+ d% o. b
}
3 n( X2 o1 y, ]7 S m_pRecordset->Close();
: K$ _9 c. G8 X2 T& C% d2 D+ ` m_pConnection->Close();
& ]6 O& J6 H! w7 |) M0 t7 d) n}: U4 | k. R- I" k% r) r
catch (_com_error e)//异常处理
9 |9 J' K8 V# X( m# T; U. o{
4 q9 ^ [ t! D/ X4 E' Y. B0 o5 q& a AfxMessageBox(e.ErrorMessage());
1 B/ @6 V8 ] u" G}
, k6 e& z* @' f* h# fm_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错7 u4 c3 i3 Z; w% Q; t k
m_pConnection->Close();$ T/ k1 J+ v( K$ X* f
m_pRecordset = NULL;! x* W! x5 c# _4 S; [! i/ ]3 x
m_pConnection = NULL;
; m6 O+ e0 Q0 j+ Z} # v8 \, {/ l t _4 J/ Q8 r
. y4 A8 w* L" v0 U. N* v. C ^
程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
4 ]. L: R) N# U5 B' c3 b/ s% _4 J/ i! z; p4 z
好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表middle中的BIG_NAME字段值显示在列表控件中。 |
zan
|