- 在线时间
- 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库环境 % h' t+ F( H0 n/ b7 s
$ y* f2 y0 j" q, d9 @4 Z
创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。
- R* @2 g- ]3 o% L本例为:
V5 z8 y2 j8 o
0 }5 A- `5 V: R ^0 S; ^% z BOOL CAdotestDlg::OnInitDialog()
0 B. J7 ]& B3 Y1 R9 c Z) L1 L {
* Q, C7 {& ~: A, [ ::CoInitialize(NULL); //初始化OLE/COM库环境 3 q7 v0 H7 v" H# T' l+ W
}
2 T- _" ]) U$ g. S' i ~* H8 z; }% u' ]/ Q
程序最后要调用 ::CoUninitialize();//释放程序占用的COM 资源。
3 c2 F: {" H7 e# R2 Y/ M& I0 \ H, W' e- r. C( R. P, o; v0 v0 h C! ?8 C) }
另外:* \; S' g) }* H$ c
; u1 l9 }" t+ j a9 Im_pRecordset->Close(); 注意!!!不要多次关闭!!!!!!!!!!!!1 \1 l! x, B B- r2 e: L2 g4 b8 [5 G
m_pConnection->Close();
0 O- J ?' h; nm_pRecordset = NULL;
4 F$ q) ]& e, }& Nm_pConnection = NULL;
( h- o# b: w" r 2. 引入ADO库文件 " K& ^, k5 f/ r
3 N g* v0 s9 O+ l2 f
使用ADO前必须在工程的stdafx.h文件最后用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下:
+ h* x- A0 x& B o#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
( t7 E/ u4 O( O) w) T* P% M" J! ^ ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。
9 X6 T, O( G$ }0 n 程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
; `0 b6 b$ v# |) k/ g/ J* P
2 z' S5 h1 F2 `- S- a" r 3.利用智能指针进行数据库操作
$ W" Z' ~# y+ L' \0 C! r+ C+ T" g* @( u, E, z* J
在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。
' Z2 S8 o: U" G
" g4 Q0 v' Y ^, j+ M% yclass CAdotestDlg : public CDialog
( {" V, M; ^, c, ?* H! S( i; E{
; U& d& U6 `, m/ a% ~$ t/ ` _ConnectionPtr m_pConnection;; z. a8 A2 } E# q# _* a
_RecordsetPtr m_pRecordset;
% z5 l% i$ K h/ X- p& I% E* A ClistCtrl m_List; # d6 k) {# I4 p& N" `: G$ u+ ]
......6 |4 p, h+ t8 g- D5 q' q" {
} 8 W* S0 {% u% \; H5 y
' U) `; @: t" F% `4 }: f* q6 H& U. ^$ l/ }
ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。2 g& b% ^! A( G
( u$ g7 d! O* S: ?: Q& W4 p _ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
. j- O/ P) [9 `. o: @" R% M! E _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。 _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。
$ y; _. t; p: {! E- W
+ R1 g8 J( P2 x; U: {/ Q. Z 在使用ADO程序的事件响应中OnButton1加入以下代码: ( ]6 ^- O0 i& ]; X; Y9 [
& |) ~* e! Z+ v( ` [* \
void CAdotestDlg::OnButton1() # K7 ^1 r6 ~9 q2 w
{. f5 C* J+ y& k, C, \6 a( h& p
m_List.ResetContent();2 h9 p% c+ s/ M/ K( U
m_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针
1 H1 q6 |2 o2 ~m_pRecordset.CreateInstance(_uuidof(Recordset));//初始化Recordset指针6 V9 Q: U. ^1 V/ Y6 |
try$ x% B. J$ o, e3 V* X) c; M
{) v2 ` v$ Z5 C; e* }5 n2 {
m_pConnection->Open("DSN=ADOTest","","",0); //连接叫作ADOTest的ODBC数据源3 o& B- g9 h2 t
//注意:这是连接不需要用户ID或密码的open 函数
3 V7 J R3 b1 q/ X; w // 否则形式为 ->Open("DSN=test;uid=sa;pwd=123;","","",0); ) \3 J* ?+ R- y8 B
7 v; x! p) z& k$ A0 M
// 执行SQL语句得到一个记录集把其指针赋值给m_pRecordset
3 {& j4 \% e1 f6 x6 D- j9 W: s8 v CString strSql="select * from middle";
* J& ]7 r2 w$ J BSTR bstrSQL = strSql.AllocSysString();
" t O" j/ I/ w, p m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText); % j3 |+ O: D* h2 `' }) x4 T
//adOpenDynamic:动态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句
7 \% M$ e/ m' b" W+ l9 ^3 _$ x while(!m_pRecordset->adoEOF)//遍历所有记录/ U: t/ C% I& `9 d3 t1 g
{ 0 S# r( j& E+ V4 r
//取纪录字段值方式之一
5 g; N( U M8 K2 t5 ]9 Z _variant_t Thevalue; //VARIANT数据类型! x# M! d E1 F, g: \1 g
Thevalue = m_pRecordset->GetCollect("BIG_NAME");//得到字段BIG_NAME的值
$ e, q4 M& L2 Y0 b if(Thevalue.vt!=VT_NULL)4 H6 a* @/ Q& s# E; A2 F
m_List.AddString((char*)_bstr_t(Thevalue));8 l5 K+ `* I' d1 v, `
//将该值加入到列表控件中# K2 i" U7 x0 o" K
9 X! k# D5 e: [" s! S3 Q //取纪录字段值方式之二
/ ?* n% o- d- R& b // _bstr_t Thevalue1=m_pRecordset->Fields->GetItem("BIG_NAME")->value;
1 x [% L3 t6 ?6 x6 F // CString temp=Thevalue1.copy();
" `2 n- v7 B+ k- k // m_List.AddString(temp);9 H8 {! ]. f* a" W$ r* q
//数据类型转换
! r u- E& u& B- r. K( S _variant_t vUsername,vBirthday,vID,vOld;
: }: m! k6 Y2 n, E/ ~ TRACE("id:%d,姓名:%s,年龄:%d,生日:%s\r\n",% g/ t+ d$ w& ^9 J4 Y Y5 L8 v: f+ S
vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);
, {6 [. s0 w, b2 U/ }5 J/ j
; p5 b7 M2 Y7 [" d. u* F$ W& r9 o m_pRecordset->MoveNext();//转到下一条纪录
4 q6 D9 r7 Z' L `8 { }2 k: m: z7 z6 G! M6 H2 Z
m_pRecordset->Close();% i4 M. U4 P5 y+ Y# k
m_pConnection->Close();
* o- A& o" \3 H# h+ ~+ y6 \: F}+ N, B$ `3 k& F
catch (_com_error e)//异常处理
- E1 {# W! G0 o9 `2 \; @{
/ `( L+ }- I4 W& f% U( v' b AfxMessageBox(e.ErrorMessage());4 ]! |3 ~2 `/ v; Q5 U; s, S" B
}
; b' b+ `9 ^/ D' \9 b9 t$ Em_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错- L# e1 K* o( Q: ~! E6 N
m_pConnection->Close();
. n: S% ?9 t! B7 i, qm_pRecordset = NULL;
$ D/ m, X% O2 `m_pConnection = NULL;
- V' J2 I5 z2 W9 s9 K4 c}
0 R4 L/ z% ?0 r4 f
1 J# r3 O I$ @1 S# O& i6 F 程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
. _; V# b% l4 A( N# f7 d
# V' R/ x, P0 o 好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表middle中的BIG_NAME字段值显示在列表控件中。 |
zan
|