数学建模社区-数学中国
标题:
[转帖]在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. B
5 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 N
void 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 @
try
3 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' A
m_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错
; D5 i4 i, f3 R; M
m_pConnection->Close();
N2 H! i) n1 X! [8 G
m_pRecordset = NULL;
. J3 E0 R& G: f& h
m_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