数学建模社区-数学中国

标题: [转帖]在Visual C++中用ADO进行数据库编程(上) [打印本页]

作者: god    时间: 2005-3-30 22:50
标题: [转帖]在Visual C++中用ADO进行数据库编程(上)
1. 生成应用程序框架并初始化OLE/COM库环境 7 e) m4 ?9 T6 B  E- S3 o
8 u" W) ?5 L7 R
  创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。
% W5 r) n# X9 B; e0 F4 J, h- N本例为: 0 ?  A; v/ T, o

$ L1 u0 N" s3 O4 [! [) N: U, @ BOOL CAdotestDlg::OnInitDialog()
* {' R' d6 L9 F  {* j {
/ V4 O: f9 b3 n: l       ::CoInitialize(NULL); //初始化OLE/COM库环境 6 B7 b; s1 N4 y5 T5 W0 p
} 0 _+ y. o1 O! ~' w2 ~3 z8 V0 a$ D* J

0 Y0 B7 i+ p  U. W6 c8 F  程序最后要调用 ::CoUninitialize();//释放程序占用的COM 资源。
+ h/ j( j) p% w. b4 X$ P! u# q
; S# e* J& @) ^5 J  另外:
8 N! u1 ~4 t# w. B5 s0 ]& `8 J( k& Q; `- l2 }
m_pRecordset->Close(); 注意!!!不要多次关闭!!!!!!!!!!!!4 j/ V% ^! X' i% Z- M
m_pConnection->Close();
1 u% Y& }2 c5 I: o! }# ?9 R4 O" ]1 E! ^m_pRecordset = NULL;
5 u# K4 ^. v% K- ]7 ^m_pConnection = NULL;
( H- _; g& i9 l0 |: y  2. 引入ADO库文件
* H1 B2 o9 M4 W! J$ W# a, f( r4 M$ y/ b) n- h% u
  使用ADO前必须在工程的stdafx.h文件最后用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下:
( [# ]4 G; z- K5 v! ~#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF"), \  [2 @) c) {; g( j
  ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。
  f' m2 E0 t, r% J1 J* b& Z/ e   程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
9 \, A& u4 h: _. y5 L& }0 _' v# u) o) h. q
  3.利用智能指针进行数据库操作
$ N" R' F/ Q. o5 }% I. j5 f1 Z8 J* [
9 I9 G( `4 n, P# @' I* S* V, a( _  在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。+ l8 F: v/ k9 d, `6 Z! P" t
, `7 D, E* y8 G3 q- C4 O  P/ r
class CAdotestDlg : public CDialog
6 |+ u* X- G+ A6 I7 i- _2 D{& M. x# I4 l2 M' \+ N- @, }% P0 ?
    _ConnectionPtr m_pConnection;
3 g4 D8 W5 p! d    _RecordsetPtr m_pRecordset;
$ I, b* H0 E7 X- }4 x   ClistCtrl m_List;
( h' B8 L; H  \$ x! c' A    ......0 }6 w/ F5 D' [# w$ i
}     
! B0 `0 D3 q! Y) r6 p* o, T
) ^: W  `% `* ^; r  ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。0 i1 s7 ]& s$ _- V) f  {5 I6 Z8 C

: S9 @; C/ [4 F  o5 i6 g7 \5 k  _ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
7 S* j! l9 G% t# P7 m* w  F" z  _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。  _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。 3 [5 H2 Y2 x8 s% h

) ?# D6 {4 I8 m4 ^7 a  在使用ADO程序的事件响应中OnButton1加入以下代码:
2 F9 C1 {9 a" H6 {" Q$ T
& r* {- O4 `6 Y, x7 H& Q' ?5 s- e7 Nvoid CAdotestDlg::OnButton1()
" _7 Q' x; l- |( L7 B+ ?+ G. m{6 E. q# u' W. ^* F
m_List.ResetContent();$ E, |5 `9 P) E
m_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针$ ]* N, J* U% k8 F. }# [" {' L
m_pRecordset.CreateInstance(_uuidof(Recordset));//初始化Recordset指针
% \. H( q* r( u) w* j5 Y. o6 @try3 P" l5 y5 a5 ?1 J
{8 X- Y" z: B$ c* d; H! `
m_pConnection->Open("DSN=ADOTest","","",0); //连接叫作ADOTest的ODBC数据源
( w& ]8 I4 {9 ^- @/ X$ W% J, s //注意:这是连接不需要用户ID或密码的open 函数
' I0 w( M7 N" _& a  Q# { // 否则形式为 ->Open("DSN=test;uid=sa;pwd=123;","","",0); $ g. b$ q- F, a6 z

; f* ?8 O4 i1 K' M7 w' d // 执行SQL语句得到一个记录集把其指针赋值给m_pRecordset
; O! [6 ^! a- o  l8 R CString strSql="select * from middle";  [% r; K5 h! r! Z  v# @4 i3 B
BSTR bstrSQL = strSql.AllocSysString();
2 t0 k$ Y4 e) ~) }: f6 [ m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);
, R4 K# _( A" w, H* ] //adOpenDynamic:动态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句! `. K4 W, T. \' R% ^
while(!m_pRecordset->adoEOF)//遍历所有记录
1 v( C. l4 F( B {
. R! _" r/ l5 ^; U  //取纪录字段值方式之一
6 \/ i, n. v! S9 W" [  _variant_t Thevalue; //VARIANT数据类型
* d  I& ~) _' Y  ^0 }  Thevalue = m_pRecordset->GetCollect("BIG_NAME");//得到字段BIG_NAME的值" O' C" _8 b$ d' v' f
  if(Thevalue.vt!=VT_NULL)
, R% `( @; S! H: A0 M# ~   m_List.AddString((char*)_bstr_t(Thevalue));
7 `3 S: t4 T1 o: |  //将该值加入到列表控件中
5 i& |: m  \% `" X2 x$ ~" i$ s7 L
0 l7 b& @$ q" R$ u. A  //取纪录字段值方式之二+ v1 M9 q1 ~) d5 \- {) n( b7 H
  // _bstr_t Thevalue1=m_pRecordset->Fields->GetItem("BIG_NAME")->value;
0 G! Z, v" v* X% |* Q- L  // CString temp=Thevalue1.copy();
0 |7 o# z3 j1 [" H6 ^  // m_List.AddString(temp);2 U# f% ?% l3 B$ V+ J6 N
  //数据类型转换
4 o1 o1 Q2 @, e& s. G! F  _variant_t vUsername,vBirthday,vID,vOld;) C0 U% m1 E8 l0 j6 I
  TRACE("id:%d,姓名:%s,年龄:%d,生日:%s\r\n",* E% ]  T. B7 ^6 w7 p0 E+ e
  vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);
, L" G9 @+ b0 B+ w. j! s
! I7 o3 S8 O! p7 x  m_pRecordset->MoveNext();//转到下一条纪录
6 f, s8 Y# H% O2 ` }
( x9 X: y4 W4 P9 N4 s m_pRecordset->Close();
! m$ E# u/ }8 E4 I2 T% Y' d0 j7 h m_pConnection->Close();
# o5 s4 ?# |9 j: l5 g2 c}$ J( y% l  u  b9 u4 v
catch (_com_error e)//异常处理7 \" a% P* _+ z# }" n
{0 M% [! N5 s( C
AfxMessageBox(e.ErrorMessage());
6 v9 S! R$ ^7 W4 L) F7 g- h, F}
) y, o0 r$ h* |7 q& s' Am_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错
; D5 i4 i, f3 R; Mm_pConnection->Close();
  N2 H! i) n1 X! [8 Gm_pRecordset = NULL;
. J3 E0 R& G: f& hm_pConnection = NULL;
! M0 T. X1 b0 P} & |+ i1 `1 A( q" p
# t: o* Q" U. s( K7 y$ k
  程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。 3 q( `, Z3 |; q0 c( G. Y  X# y
4 f( d; }* b6 L. Z: F
  好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表middle中的BIG_NAME字段值显示在列表控件中。
作者: chenlk    时间: 2005-4-9 16:35
有用




欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5