数学建模社区-数学中国

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

作者: god    时间: 2005-3-30 22:50
标题: [转帖]在Visual C++中用ADO进行数据库编程(上)
1. 生成应用程序框架并初始化OLE/COM库环境 * B) J& h2 ?  W8 w) s6 ?
2 r8 h& w0 X# ^; _6 Q* D. c6 S5 c
  创建一个标准的MFC AppWizard(exe)应用程序,然后在使用ADO数据库的InitInstance函数中初始化OLE/COM库(因为ADO库是一个COM DLL库)。
. {0 G. e! \+ y6 O8 v& R本例为:
# O+ \) r0 R* b6 M
; Z. v- Q2 ~" I+ J8 D BOOL CAdotestDlg::OnInitDialog()0 x. q* r3 K  r
 {) U0 w, p3 G4 V9 {
       ::CoInitialize(NULL); //初始化OLE/COM库环境
) ^6 |3 l' J" J5 M  x- X6 S } ! b2 X4 c; i  e/ {& e

$ m& ]6 ?% U3 v3 o8 Q3 [  程序最后要调用 ::CoUninitialize();//释放程序占用的COM 资源。
- H8 K7 W7 p5 A7 d2 |
& ]& J7 y. a% r* a  另外:
6 h: V; a* g) z) l( C+ V: w' q7 @& b
9 {7 y& U; z/ d/ O3 m1 K8 c8 P' ~m_pRecordset->Close(); 注意!!!不要多次关闭!!!!!!!!!!!!
! q, r' v- s! v/ dm_pConnection->Close();
& f3 ]8 M7 G9 c7 k6 J9 k* Vm_pRecordset = NULL;9 b5 U  d- F2 m/ U& J' |2 v1 H
m_pConnection = NULL; 8 h4 n6 ^+ K6 s& |; e" ]
  2. 引入ADO库文件
- W2 H# p6 k9 c4 k# C$ A% `8 B, O
  使用ADO前必须在工程的stdafx.h文件最后用直接引入符号#import引入ADO库文件,以使编译器能正确编译。代码如下:
$ X( J' A9 }" y* e4 u/ j% k; l#import "C:\Program Files\common files\system\ado\msado15.dll" no_namespace rename("EOF","adoEOF")
) C; Z+ s* o: _  ADO类的定义是作为一种资源存储在ADO DLL(msado15.dll)中,在其内部称为类型库。类型库描述了自治接口,以及C++使用的COM vtable接口。当使用#import指令时,在运行时Visual C++需要从ADO DLL中读取这个类型库,并以此创建一组C++头文件。这些头文件具有.tli 和.tlh扩展名,读者可以在项目的目录下找到这两个文件。在C++程序代码中调用的ADO类要在这些文件中定义。
1 j3 u, V, m0 Y" ~) M) t   程序的第三行指示ADO对象不使用名称空间。在有些应用程序中,由于应用程序中的对象与ADO中的对象之间可能会出现命名冲突,所以有必要使用名称空间。如果要使用名称空间,则可把第三行程序修改为: rename_namespace("AdoNS")。第四行代码将ADO中的EOF(文件结束)更名为adoEOF,以避免与定义了自己的EOF的其他库冲突。
1 [% c, P2 A/ m, O: y
, x9 Y, T+ G' V) l  3.利用智能指针进行数据库操作 1 p4 s- m* @; F3 ]$ y
% s7 s5 u- t: A: g  N7 \( t
  在CaboutDlg头文件中定义两个ADO智能指针类实例,并在对话框中加入一个ListCtrl。
, k) N9 q% i, a# o8 X+ ^8 |+ ]5 a" P; R6 y2 t" j
class CAdotestDlg : public CDialog% w' I, x: \) {" p- X
{9 Y( @! n5 x: z( V( h! i! Q
    _ConnectionPtr m_pConnection;
+ L# B6 {' k/ b9 e8 h; y4 a    _RecordsetPtr m_pRecordset;7 T* _  y4 V" {1 ?' z) u
   ClistCtrl m_List;
: E) C; n) T8 Z5 k5 C2 F* t    ......
3 g5 n; r. N1 w}     
3 r! V) k# b5 W3 x- z+ X% Q* J) `
  ADO库包含三个智能指针:_ConnectionPtr、_CommandPtr和_RecordsetPtr。) S5 I+ }+ G- b9 S. L

5 ~+ v8 D6 b; r) |- |- A( n# A  _ConnectionPtr通常被用来创建一个数据连接或执行一条不返回任何结果的SQL语句,如一个存储过程。
* u0 A9 s1 |) N' K  _CommandPtr返回一个记录集。它提供了一种简单的方法来执行返回记录集的存储过程和SQL语句。在使用_CommandPtr接口时,可以利用全局_ConnectionPtr接口,也可以在_CommandPtr接口里直接使用连接串。  _RecordsetPtr是一个记录集对象。与以上两种对象相比,它对记录集提供了更多的控制功能,如记录锁定、游标控制等。
, r0 z# T: F9 `, o+ j! C$ ]7 Y( n! O1 X5 b$ C; l+ d. L
  在使用ADO程序的事件响应中OnButton1加入以下代码:
9 _4 e$ J5 w; ]( W- R3 _5 n" C5 }0 |& x8 s: ^
void CAdotestDlg::OnButton1()
3 n9 W- Y$ j# b6 U, Q{/ {4 ?9 L8 I# R* c# t5 @, F  w: {
m_List.ResetContent();
2 j3 l3 b8 ?$ E+ f; |6 xm_pConnection.CreateInstance(_uuidof(Connection)); //初始化Connection指针( X2 b& Y+ i3 e4 H
m_pRecordset.CreateInstance(_uuidof(Recordset));//初始化Recordset指针) l" y& ?: A# l0 G% _
try+ b* A. u0 W+ Q! W9 y. U+ E
{  _$ G6 @( z& l2 g
m_pConnection->Open("DSN=ADOTest","","",0); //连接叫作ADOTest的ODBC数据源3 _2 F3 C+ T( D9 M3 I
//注意:这是连接不需要用户ID或密码的open 函数
  C5 [+ I2 l6 l$ | // 否则形式为 ->Open("DSN=test;uid=sa;pwd=123;","","",0);
& ~. q9 E4 b# i5 b7 ?7 K5 q3 e9 c! Q+ h+ e: y$ R1 K
// 执行SQL语句得到一个记录集把其指针赋值给m_pRecordset
/ T' N% c/ S/ L: s CString strSql="select * from middle";
  o# t& t3 f7 X% ?0 a7 y  ^8 E BSTR bstrSQL = strSql.AllocSysString(); ; C! r4 b. @# o: T% k0 P' ?
m_pRecordset->Open(bstrSQL,(IDispatch*)m_pConnection,adOpenDynamic,adLockOptimistic,adCmdText);
; a5 h7 x7 O! y //adOpenDynamic:动态 adLockOptimistic乐观封锁法 adCmdText:文本查询语句% ^, A0 m$ S( o! Z, i
while(!m_pRecordset->adoEOF)//遍历所有记录
' H/ _" ]% p( c. m  H { 0 n7 F$ P/ L9 }0 N
  //取纪录字段值方式之一
  o" \: t/ X5 A  P) e  _variant_t Thevalue; //VARIANT数据类型+ n1 h8 z( m& w  \! x0 d0 ]
  Thevalue = m_pRecordset->GetCollect("BIG_NAME");//得到字段BIG_NAME的值' a  M  [0 A/ }; P2 V( K
  if(Thevalue.vt!=VT_NULL)3 D# E5 |8 r0 e% U" ~
   m_List.AddString((char*)_bstr_t(Thevalue));
2 F) H& [2 B/ ~5 n- E6 a  //将该值加入到列表控件中
, x2 W# \% K6 Q3 L4 F/ F' e
  m, ?3 n- ]" d0 t, _, x. z1 W' q  //取纪录字段值方式之二
: p, Q+ R: P+ \$ c0 X$ |  // _bstr_t Thevalue1=m_pRecordset->Fields->GetItem("BIG_NAME")->value;4 J4 h$ _% }! t# J/ W4 }" X3 ^; p
  // CString temp=Thevalue1.copy();2 }  S& |8 K# I: E$ a
  // m_List.AddString(temp);; @- v5 o0 m3 w5 e7 C9 @
  //数据类型转换) E. L; g* j" X
  _variant_t vUsername,vBirthday,vID,vOld;4 m* u! T+ F$ {( z3 E
  TRACE("id:%d,姓名:%s,年龄:%d,生日:%s\r\n",
( n7 q% A- U3 [  vID.lVal,(LPCTSTR)(_bstr_t)vUsername,vOld.lVal,(LPCTSTR)(_bstr_t)vBirthday);
6 x- Y, Y% B$ m' ?- Y7 A. `" N, t7 X( H1 z3 \" Q. ~  N4 Z# D# Q
  m_pRecordset->MoveNext();//转到下一条纪录9 ?4 [( k* H6 D" F
}6 g3 q; O1 b+ i7 P+ ~5 V0 T
m_pRecordset->Close();
+ u( v8 H% _2 q  T0 f/ @ m_pConnection->Close();
: [$ _4 k0 P$ x' f+ W9 D7 a, h}
2 H( k. M% \8 X+ H; P* Ncatch (_com_error e)//异常处理) B# R/ L# Y: I, l# Y: `
{
% p9 s: d. f9 J7 O: d" \5 G! R AfxMessageBox(e.ErrorMessage());2 _* S! |: L2 k5 g) D& k- S1 l! d+ |
}
& x; |4 R/ }9 ~9 b2 H; ~8 x2 o) t8 Ym_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错
( v3 F* z8 C5 L! F2 mm_pConnection->Close();/ Z& w) m: g; i9 w0 {
m_pRecordset = NULL;/ [* J  U! |: ]" S
m_pConnection = NULL;
: k  S  ]9 s4 y+ z+ v}
) W  ~8 s  ]+ y& g% _0 g  p7 I( t5 y0 A$ L: c0 Z
  程序中通过_variant_t和_bstr_t转换COM对象和C++类型的数据, _variant_t类封装了OLE自治VARIANT数据类型。在C++中使用_variant_t类要比直接使用VARIANT数据类型容易得多。 ( R  V, @# M1 |

4 ?. i' {5 E: E- A2 R" x  好,编译后该程序就能运行了,但记住运行前要创建一个叫ADOTest的ODBC数据源。该程序将把表middle中的BIG_NAME字段值显示在列表控件中。
作者: chenlk    时间: 2005-4-9 16:35
有用




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