找回密码
 注册
查看: 4605|回复: 0

[收藏]VC++中调用ADO的常用方法

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
# w2 F/ R: m: s# V
+ h, K+ c5 `: r& o2 l9 a1、 用import导入ADO 的 COM 文件msado15.dll
  @/ J9 k( R9 L
& x$ N9 E! \% H3 [* ?例如:# i9 C& j0 M  @2 T$ b0 T% y

9 [% S6 W) D9 i  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
% O. g( ^& w+ L5 L
! T3 o( I+ f- H* h: J8 _# j   no_namespace
& h8 i7 X3 `5 N9 r5 }2 d7 H$ V7 T( D) A% ]5 D9 o! P! K3 h

& X1 I1 _2 k3 {; B  X1 p2、COM 使用时初始化
, |3 h5 _( W3 G) ]% u& l5 d6 |% B  X& i) c( o( ^
HRESULT ComInit()' w6 l- Z! p' _8 L
{ / a: K' [% _/ ]" ^) P# W9 }
    HRESULT hr = S_OK;             // 默认返回值- a$ r9 {( y$ A- h1 L& a! v; e$ N+ Z
    if FAILED(CoInitialize(NULL))  // COM 初始化调用
- [4 L( @* i( l: @4 |    {
) j. K. ^. M% ~6 {7 n) F        CoUninitialize();
. J/ F2 K4 F+ A; y/ D        hr = E_UNEXPECTED;2 K! Y/ Q5 \! Z) W6 R: \$ C
    }
3 k3 W$ P; y! m8 @- {& T7 p    return hr;
5 z4 m- C" r) i2 {9 X4 ~}2 y7 e3 A$ L* b: @- t# }: G

! c* e. Y) Q+ L  }- F3 q- J. s9 }+ ~* p- y9 p9 w) a
3、建立数据库连接& d. [' O; l8 Z
- n+ k& M/ s7 C0 u. X7 K+ J" v
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名, ]7 B4 A- |9 v* |) o2 u( H  Z, S# ^
                     LPSTR pConnString,                 // 连接字串 % E1 P) c9 ^; O9 q  |  P
                     LPSTR pUserPassword ,              // 用户密码# K+ q; L' {$ d4 c0 _& X! _
                     ConnectOptionEnum ConnectOption )  // 连接参数9 C+ k: |8 [' Y3 k* L8 |1 S1 F; b# ~
{7 o; F8 x3 L6 u: Z4 J3 j

" I* C( k' B3 i: i; O# ^    HRESULT hr = S_OK;        // 默认返回值. [. z; c1 K. B1 d, F9 i
    _ConnectionPtr ptrConn;   // 定义Connection对象  u3 G" |9 q7 t; Q2 o5 V

5 E( M$ I2 j! G( U3 U    try. K; G1 q0 N5 c
    {% F5 v- _1 M  r
        // 创建一个连接实体# `$ _# F0 s3 f- s/ a' c6 h
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
( f) Q( t9 B* r
. I3 p" U! p0 |8 \# O        // 设定连接等待的最大秒数,默认是15秒
( t! `  M7 c9 p7 `. j$ ]- r* n' [        ptrConn->ConnectionTimeout = 20
4 ]4 W- K8 h6 E. H; ~" H
, ]( _9 F- R9 y  M, h        // 打开连接' C( @: h8 W4 S- M. y9 j$ f
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );2 s- M. r) y" Q# p
        return hr;/ ~8 \3 W7 S5 ]7 _( B9 B
    }2 L( ~6 {4 ~$ e" r0 X! Q+ Q4 I% j' r& ?
    catch( _com_error & pComError )7 U- Z0 S" v: D6 `* E6 `+ @
    {0 K* U5 `5 N2 |4 u" O6 E
        …… // 错误处理6 Q; O% `# X# H& M( u9 L
        return E_UNEXPECTED;
8 v7 o- V( Y( b! K0 z7 ]' c    }
  x1 W1 {" m6 C) K& c}
% s3 {3 v' B" o# ~8 M/ R* y- @# S- J( u

6 a# Q+ |# C9 ~$ A9 s4.执行一个SQL 查询,得到数据集(recordset)* K9 L$ J1 X( `

  k  N9 g2 @& I2 Z_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
/ F3 S! y" k4 `# o$ g- l{
  m+ R* @/ d% }% e    try
& X- [* S8 r8 L* Z4 H% E    {
4 e) [+ R2 D- F) K: |4 x/ P        RecordsetPtr ptrRS; // recordset 对象- @  Q* Y- L$ p
  L7 d8 O" y/ S6 e9 z& O" u5 L
        // 创建recordset 对象实体
4 s6 |5 G. b. o6 o+ ~: P) i% d" `        ptrRS.CreateInstance( __uuidof(Recordset) );
6 Z7 h* w8 L3 k! B2 \/ O* x        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, 4 b% e( S/ c: N3 W. ?
adLockUnspecified, adCmdText );" L% \# I3 ^; o. `5 V
1 U1 o( R. Z& Q1 K5 {1 A
        或者
4 ~  J. T5 K3 i4 ~, t        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
8 m( [/ c! y0 J# s5 y0 q        return ptrRS;; w, W0 M1 g/ Q2 s. X
    }3 {, R& Z/ g8 z! T9 H
    catch( _com_error & a_pComError )6 Z% O9 K; H" l: |0 Q
    {
6 r$ k# |) O- x; i3 R9 v# J        ….// 错误处理
# T' c$ U0 k: ]( O1 W* r        return NULL;  i+ H  E* ]/ f" H5 |% z" a
    }
9 f. e' l, I& M+ v5 R% Q% G# z}$ C6 f! _7 L- j% V
, I/ A0 a# m: h1 ?8 Q

! \, Z7 c: P" T7 m9 A# Q5.通过数据集(recordset)得到列的名称" a% F! _) j8 c- @' D0 I
. ^8 l( N+ U& W$ J6 i4 Z
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
4 \% J$ v2 x+ h, i' ~                        char strColNames[][255],
! I" T. S* E6 `                        DataTypeEnum iColTypes[] )
; F9 t9 }" D! L. H+ }+ [{3 f& M) g1 O2 C5 r, L0 l
    try
4 A/ r# U" w& ?    { // 参数变量% v* W, p: b) E: H. v" R
        _variant_t l_vaIndex;8 N9 v" _. M, r! R) w. a( J) a
7 Q$ _) [0 w2 C) ^; p- \/ ?* ^
        l_vaIndex.vt = VT_I2;' i6 e  `0 x% ~4 m9 m
, h  b' w& m4 q: _6 O- n
        // COLUMNS总数
9 H8 w0 O) e6 p1 v        long lColCount;. |% S: |; _1 F; F  m7 V
0 B1 R# l, E  s4 E8 m( \
        lColCount = ptrRs ->Fields->Count;5 H# b: ~0 k7 ]" }' Z' g( P4 f
) e1 g6 v3 m9 X. M
        // 循环取得列的属性和名称5 _1 ^8 i9 z% J1 O! Y# d9 {2 d
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
$ b3 q& f  O# h/ v" [0 C2 T2 N        {
: j' h; V1 M' i            l_vaIndex.iVal = iIndex; // 设置循环索引
5 W, v4 c  P! s* [8 V0 j7 L% u. z
            // 取得字段名称
* E2 k3 H% C' b7 c3 Z/ l            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
3 f3 R& ?% i% l! ^
% [7 K$ u; H, Z0 E" Z. ^            // 取得字段属性3 v1 U$ l- D% s" T5 t" u8 s
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;0 a% K: ]9 k5 v7 ]5 H$ Y
        }0 Z& c6 m6 r' v6 d$ m3 C/ _
        return S_OK;
; u& _9 J$ i' S' K    }
, A  |7 Q9 F6 D9 F* a3 R. J    catch( _com_error & a_pComError ). E, J- |3 H/ F# ]. K4 M9 p. I
    {+ ?0 q4 b4 N9 o4 x1 `* ]; ~, E9 c
        …. // 错误处理9 b( o# |. ?8 l2 c
        return E_UNEXPECTED;
7 S. ^: N$ Q+ C8 W& ?. X% l% H    }: A) F* V  e) |6 ^& r2 l( r) F
    catch(...)
; D0 Q0 a/ L8 |$ M) A$ v    {" ~8 z0 o, a. \' W: q3 v% q
        …. // 错误处理# P& e' J" Q5 T7 Y# V( v8 K/ d$ u) M
        return E_UNEXPECTED;
' u8 u2 c) U( q$ e& z+ Z    }
% C4 @) o, W! C; c: R" ^- K}
4 M8 |4 I* |# ]" ]; {( j/ b7 j" |" H+ K: ]9 u  \
7 i( I& [; d5 L9 A- X5 n7 h
6.通过数据集(recordset)得到当前行记录
; f( h8 E0 u# U
, @. ~8 o% d9 P9 G  a1 rHRESULT getOneRecord( _RecordsetPtr ptrRs,9 ~8 h1 |( {& r0 _) x' n
                      const long lNoOfColumns,
' L1 J! K# t$ o4 z7 G9 l+ o% S                      _variant_t varValue[] )
! d, I& Q: f3 z" x7 f8 e7 c- Q* w{
& G! y! r2 n" b" ^, M7 w    try
7 j# R  v! U7 L9 n9 ~" r    {
1 s! g/ x" i; Z0 n        // 参数变量
2 i6 G3 `% z9 g; C" @        _variant_t l_vaIndex;4 L. j7 _: \, Q  A
        l_vaIndex.vt = VT_I2;  f) n- ?8 C6 {& K% @' h+ [
  t3 K2 X% C) ]
        // 循环取得列的值
! a5 v! N9 p; r3 A. r" T        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )- T/ W+ m$ b% u7 @
        { 6 U, P7 l! B) s0 q& j
            l_vaIndex.iVal = lIndex;( T8 ~6 _( u0 @6 r- P* p- G, z
/ o7 j9 X5 n9 b3 O  e- Q  r2 t
            // 取得字段值
' B! i% P; Z! h            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;( l9 \; I' h& q& {
        }
: h3 h9 X$ ~7 k! [  j  K        return S_OK;! }1 T8 m9 v- @5 n1 V
    }/ C! y6 p' k* ]# J  k
    catch( _com_error & a_pComError )
7 }/ w' e, g' \7 J: ]5 g2 x    {
8 u6 \6 u, Q% i" Z        …. // 错误处理3 F/ V) v* R7 M# \8 P3 g
        return E_UNEXPECTED;
% C& b1 b  ]/ J0 E, F5 l    }
* u8 p) W1 y5 ?3 f    catch(...)% ?: k1 v3 _' U/ p9 E& L/ ]$ t- f) W
    {2 m7 y3 w3 [" ~. J
        …. // 错误处理& t9 _4 g9 d/ i/ k2 a4 i$ O
        return E_UNEXPECTED;
. |  ~3 x1 ~% }    }2 a; {+ v4 a7 n( V
}
( x6 x% t% g9 T) b+ [
+ s& x3 j% U/ u( ]8 R; L! D, A1 ^! x8 B3 @
7.出错情况下错误信息的取得8 \9 H* ?5 y0 M. g5 k8 o
7 [7 a( }+ l. G: ^( u; k
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );$ r" g6 f. c* @  g' q0 o
{9 ]! u2 }( x( _0 y) E. P
    // COM 错误取得) }+ J' h% g) i6 T7 U
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
# c: F6 B0 t  W/ H9 ~! U    char lpComErrorStr512];
# k. O9 H+ K: s9 u* X" M% F; q" e- L" ]3 \
    sprintf( lpComErrorStr512,' E* p" H3 d" C; v' [
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",' v- O) q  k( h+ Z9 Z2 \2 E' G8 o
             pComError.Error(),                  // 错误编号
( |) g7 d4 F0 J* }% k2 q  M: n8 z             pComError.ErrorMessage(),           // 错误信息/ M+ D1 m/ o  u+ @. l9 R' Y
             (LPCSTR) pComError.Source(),        // 错误源
* q' b$ n2 g  x+ ?; ?             (LPCSTR) pComError.Description() ); // 错误描述
! v$ M# h7 n2 q  h+ }( u3 r( ~+ N! S( I6 ^3 |
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
8 O# o# f; t6 G% f% y    // ADO错误取得% v" V! j# {5 d3 S& y

/ h; r0 c6 j- D' w- d' R- @' j! F  V    ErrorPtr pErr = NULL;
$ G' E4 m" K& w/ t' Z; V    if( (ptrConn ->Errors->Count) > 0)
3 Z+ x  m. y+ C9 q' k1 a    {
. x1 e0 Z- Z" o# @1 q8 |7 [7 f        long nCount = ptrConn ->Errors->Count;
( T$ u/ |" u$ s: L- n        for( long i = 0; i < nCount; i++ ). t' p1 g( r, ?* `6 r( x6 m
        {
: v  o. ]% B! M5 b/ {) {            pErr = a_pConnPtr->Errors->GetItem(i);' V. u( ^8 Q5 w2 k# U; v3 b6 A

$ r' \' r/ {: |) Q; F            char l_pchErrorString[512];
' n0 i- a$ }% |- y) J" q: V/ b            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",$ ^/ \7 b2 a4 ^8 S. `. i
                     pErr->Number,         // 错误编号7 N5 a8 r1 b5 c( [6 Z5 q' S/ y1 C
                     pErr->Description );  // 错误描述
! d/ {1 T* J- X7 e, H6 u9 t        }
7 R# B; ]- t9 O7 P7 G7 k' x    }! s$ d9 q" \4 c  @6 U
% w8 \# f0 e9 T" d4 Y
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
- C  T% v& e* t! _    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|宁德市腾云网络科技有限公司 ( 闽ICP备2022007940号-5|闽公网安备 35092202000206号 )

GMT+8, 2026-10-1 20:49 , Processed in 0.016067 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表