在线时间 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库环境
& Q6 N/ J; \2 j
# Y* Z I3 J+ G4 X& ~' H1 S) [- G 创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。
+ f; G3 I3 o: v1 o3 J 本例为: 2 `# I2 T6 ?9 T" o0 B
: R! B' @# A% m" i! T BOOL CAdotestDlg::OnInitDialog()4 J4 S( A1 G- U
{. @+ t+ N: U5 k# e
::CoInitialize(NULL); //初始化OLE/COM库环境 , n. c+ K8 W# [' @9 t3 F4 v
} - E; o! ` q( a5 o, O
6 E0 p3 t5 y w. B$ ]- F 程序最后要调用 ::CoUninitialize();//释放程序占用的COM 资源。
# d) a) e6 M7 r& a: k% a/ j5 C
( h% g2 |0 E9 G# j% _1 q" h 另外:$ B7 M( ^( E1 o1 V
% T; [# K0 _# y m_pRecordset->Close(); 注意!!!不要多次关闭!!!!!!!!!!!!
$ n; C j$ h8 C! L: {% Q m_pConnection->Close();
$ `4 q1 l( C" [* ` m_pRecordset = NULL;% C: o$ J0 H% \" e6 w8 p' p! \
m_pConnection = NULL;
3 J8 H% Q: A; e" d) x 2. 引入ADO库文件
2 W% d! q7 k3 X" s4 r" b% c 9 ~0 S8 s g, b& y/ K
使用ADO前必须在工程的stdafx.h文件最后用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下:0 q& I+ x5 T7 |% _) _! Q
#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
( n* }9 `, @( t5 I. @3 X ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。 ! a" _0 N: W9 l" ~1 b1 C" O/ w6 c
程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
7 T0 P$ `+ L( n$ b" m! D1 a , ?* f2 F0 b/ S" ]
3.利用智能指针进行数据库操作
( c4 z6 d7 u" ?* ?
* k) M- W3 t+ w' ~7 d 在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。& j# i: G7 O, L2 L3 ^
2 A- R7 P/ |' o class CAdotestDlg : public CDialog
/ J# D! }% p- x' h$ j {
' P `* @+ u6 N! q; l' x- o; @ _ConnectionPtr m_pConnection;6 `0 C0 s, s0 @- b6 i( w L, e
_RecordsetPtr m_pRecordset;" r: D0 f2 |' @- w! u9 C j
ClistCtrl m_List; ) o3 T6 \& i: v) g
......$ ^8 _( k e) E4 q c
} ' o% u5 a3 W q0 k$ b/ C: P' @
" `! J' o" N: n1 v& h ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。7 T4 |& S: ?( v2 d/ ^! _" C
2 V( d+ K& v$ Z/ t _ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
/ G m8 J. P' e9 A( Y _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。 _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。
8 M9 w8 R) [5 D
* [. D& T5 x1 Y6 X. K 在使用ADO程序的事件响应中OnButton1加入以下代码:
! f; h$ ]/ E# q! Z, [ i
; R. d$ E3 l: w; j$ k void CAdotestDlg::OnButton1()
. `% j0 |5 U/ v6 l0 F T {5 ^, T$ n! w8 }% K/ Y2 Z
m_List.ResetContent();* F& y5 q8 I1 a0 }! q4 u
m_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针% l# G, K* k8 [5 m
m_pRecordset.CreateInstance(_uuidof(Recordset));//初始化Recordset指针9 H0 Q0 H; @$ I
try+ v6 C3 d) b( ?% |5 R$ [
{
. L4 I4 r# w" s- j0 |) p' w5 T m_pConnection->Open("DSN=ADOTest","","",0); //连接叫作ADOTest的ODBC数据源# F! ^5 X" ]* N; N
//注意:这是连接不需要用户ID或密码的open 函数
- q R( ]9 ~% [% |$ k! ~* E+ [ |1 n5 i ~ // 否则形式为 ->Open("DSN=test;uid=sa;pwd=123;","","",0);
# x( @9 j4 N& W8 ?1 @$ K) ?8 j" `
6 T b7 x9 @% a8 U% S // 执行SQL语句得到一个记录集把其指针赋值给m_pRecordset9 Y, R7 [2 V j. \* i
CString strSql="select * from middle";; r; [9 S! K) o/ L6 k
BSTR bstrSQL = strSql.AllocSysString();
% S: P4 Y, t( Y, z/ X m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText); 2 i$ G; y, C! X/ s
//adOpenDynamic:动态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句- F S: P4 U( G/ j7 W
while(!m_pRecordset->adoEOF)//遍历所有记录1 X9 f( n" u/ T$ g7 _% H) C4 ~
{ 3 B" V" a3 A0 x3 V
//取纪录字段值方式之一
/ Y7 ]7 }2 X2 ^6 a: I6 Y _variant_t Thevalue; //VARIANT数据类型5 _0 F9 o# Q4 q7 W# L: l
Thevalue = m_pRecordset->GetCollect("BIG_NAME");//得到字段BIG_NAME的值
: S8 L( A# Q5 i. R; \ if(Thevalue.vt!=VT_NULL)
3 G5 ?1 B8 U. `6 |' b# u& G m_List.AddString((char*)_bstr_t(Thevalue));' g s, u- m$ K9 E
//将该值加入到列表控件中6 q4 o O) a! H' U
6 d# M. Q! I) w( i8 L
//取纪录字段值方式之二4 J3 V4 j6 [1 I( t
// _bstr_t Thevalue1=m_pRecordset->Fields->GetItem("BIG_NAME")->value;
! v0 h+ Z- S. L/ E$ c // CString temp=Thevalue1.copy();
0 S) |% {5 L- W" o // m_List.AddString(temp);" w) [) c5 n) u$ F/ D
//数据类型转换
, j! b' x1 f. X C- T+ g0 V _variant_t vUsername,vBirthday,vID,vOld;
$ Y( j# ?, g+ V. w, Y+ Z TRACE("id:%d,姓名:%s,年龄:%d,生日:%s\r\n",
. V+ A6 O& d' E# \ I vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);, r4 f) U( Y* Y8 r$ Z6 U
; U* Q8 r+ _0 E1 ^
m_pRecordset->MoveNext();//转到下一条纪录
# Z2 e/ m. c& `: E* p }: q$ A6 [9 E7 q2 Y
m_pRecordset->Close();
( r4 c, _. f' f% D m_pConnection->Close();. N6 `" K/ o6 L1 C
}- y0 D" B9 p/ }$ t9 b
catch (_com_error e)//异常处理0 _$ U( c$ f& S/ n L
{) l+ ? L; C/ {; g8 g! N- `+ k
AfxMessageBox(e.ErrorMessage());
, |/ Y" V( K7 j3 ]* K6 Y: Q }4 p" i u, x% x0 ?
m_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错
* l" T+ a' a9 s6 ` K m_pConnection->Close();
; q% D6 ]( Q7 i m_pRecordset = NULL;
# {! U* c8 a: i- `- s m_pConnection = NULL;
. p1 t- L6 m% e }
5 E2 x# b3 b. n! l5 A( @
6 u; P/ {, R t/ ]( l/ d1 h! b 程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。
% W# r& _' I U8 ~/ g% R( ^ 0 H1 ~9 V5 _/ M
好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表middle中的BIG_NAME字段值显示在列表控件中。
zan