数学建模社区-数学中国
标题:
[转帖]在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/ d
m_pConnection->Close();
& f3 ]8 M7 G9 c7 k6 J9 k* V
m_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 c
4 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 W
3 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" C
5 }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 x
m_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 q
3 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, t
7 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* N
catch (_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 Y
m_pRecordset->Close(); //注意!!!不要多次关闭!!!!否则会出错
( v3 F* z8 C5 L! F2 m
m_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