找回密码
 注册
搜索
查看: 4219|回复: 0

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。: M, o- a! u0 Z

) k* d1 [/ e. F& ?. N- Q  h6 H/ o; M% @1、 用import导入ADO 的 COM 文件msado15.dll
# P- {) J# O/ v0 y% t5 G4 p! r* o+ H8 G7 C- x+ Y
例如:
, K7 M  q7 t3 a9 u  o  \0 \& e3 C- Y' J3 `8 G
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
, ?' N$ G. B. [0 K$ V: R) M
. C* K$ O3 g8 @- c  ]( c   no_namespace, i3 u3 _1 N( `' K! f3 m9 {) c

" }# y0 ^( k' J$ @& ]; {+ l3 r
" [( _8 t& n% v; R3 k; ?8 Z4 x2、COM 使用时初始化
# v/ D9 c  q& _1 d. E
2 k0 K, L$ j1 r, s! b5 P8 n- U0 AHRESULT ComInit(); k; L3 k3 Z: d. ?+ _- o
{ 8 V$ P+ u0 i1 i' ]) b9 |
    HRESULT hr = S_OK;             // 默认返回值
. D6 T0 K5 n/ x    if FAILED(CoInitialize(NULL))  // COM 初始化调用1 q5 q5 n; F/ g# C4 n8 i8 t
    {
7 P) u6 e  V, ^! @/ f1 y        CoUninitialize();) ^0 }9 H' ~. e
        hr = E_UNEXPECTED;$ C* ~, b+ y6 l3 W( a, j' k
    }8 h6 ~* P& y/ a" |
    return hr;4 ?; m4 t1 G8 w
}0 j- z/ Q* y; D: `; v
6 `& ?0 y+ X, A* Q9 _
; x9 J+ q0 L% ^/ T% b" ~
3、建立数据库连接
2 O" ^% @! I8 }3 u; C  k. R1 @+ @+ ]" m; M" x
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名% b) [6 j4 J9 E* f& ?0 H% L
                     LPSTR pConnString,                 // 连接字串
7 G. d* i0 @) ~                     LPSTR pUserPassword ,              // 用户密码8 n9 a! n( K# L) F2 _: t
                     ConnectOptionEnum ConnectOption )  // 连接参数
! M" {+ m% b( |# {) d. K7 N# ?{+ k4 k3 ^* J# R% x' m- [; c

3 n9 a4 R/ ^3 ?' F    HRESULT hr = S_OK;        // 默认返回值0 w) e/ S) y! X; c& R2 [
    _ConnectionPtr ptrConn;   // 定义Connection对象( E5 i0 O9 L  C: L' M8 v
$ j0 I) V1 ?4 F" u8 K! l
    try
1 p. K) G* Q$ V    {- Z9 t7 d  t- l
        // 创建一个连接实体# ?6 s- h/ B/ }( q' q" w% s2 \
        hr = ptrConn.CreateInstance( __uuidof(Connection) );! X9 D) u. H3 {1 E& o1 }

  F* e" ~0 J9 O8 G        // 设定连接等待的最大秒数,默认是15秒/ u4 s* l# z# ~. `; r/ k* O6 ]
        ptrConn->ConnectionTimeout = 20
) M) J  e. W/ d' J7 ]0 W7 e' r0 `4 O/ T$ H
        // 打开连接+ }. a& ]5 F% G* |/ U) N. d( h
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
* x8 t# J7 B. N: {4 z  J) q        return hr;# Z( f- q$ |1 i  d
    }
7 X9 H/ D/ E1 U, k    catch( _com_error & pComError )
( S. _' H4 R2 p/ k' z0 C1 N0 ]) p    {0 [: P6 \' o$ L" e2 t9 C
        …… // 错误处理& J! ]7 E, [2 `( R
        return E_UNEXPECTED;
; w  p! d4 Z) t# J    }0 d2 M" I5 W- ~8 }6 M6 {
}
6 C3 w/ n3 e$ F9 q  L) ^' J: y6 {( [" k! L5 e% k$ N

. w, G) q. B' P( d8 ]; e4.执行一个SQL 查询,得到数据集(recordset)
  _, P, T1 j/ e2 u5 N: k- C9 h$ S* m
; i3 s4 I& `  F, M! ^_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )# d9 o% T0 ], v: x/ h
{7 a3 Q" f% }0 q( {
    try" m$ J& w( X7 r
    {
# @( I; V/ t. ^8 Q; F, ]6 G% l' Z        RecordsetPtr ptrRS; // recordset 对象/ m3 e6 b& b  z1 m' Q6 c
$ i9 \# E, O+ i. \% e6 S9 I) c& p* }/ S
        // 创建recordset 对象实体' G5 j3 U+ K. H+ h; N7 G
        ptrRS.CreateInstance( __uuidof(Recordset) );: t& M+ p0 ^: Y( j1 M: i4 M: ?
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
8 w6 w8 C4 y/ y7 U! i8 D9 S, `adLockUnspecified, adCmdText );
. Y! N) L( Y$ O. X$ o( o
! k& c, ~: K+ Q        或者
* a% W0 E! K  X6 P! R1 Z/ r        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );8 {1 P0 E# @, I2 f& `6 E4 `% N0 T5 l
        return ptrRS;
/ [& A- X% A2 ~! U    }* X, Y: `" L6 D
    catch( _com_error & a_pComError )+ r- j0 k7 R( L4 ~+ W0 \
    {0 c* M8 F, @4 F! k
        ….// 错误处理, G6 y* ?; C+ B* y$ p' X6 C5 a
        return NULL;
$ M0 t5 }$ S0 e' L7 O; K: g7 N    }
. |0 c1 x/ y6 |  _1 L* J3 w, _}  U1 @3 z4 ]6 W+ w1 ~6 m  f% H

9 g% j( X& s# g  X8 W( q
& q/ v/ R% T1 U- t( X) B5.通过数据集(recordset)得到列的名称
" Q  f4 p6 U, J: A
6 T5 X/ X5 ^- \  t5 zHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象) ?7 t3 S" Q+ N( p% ~+ {# q2 P0 u
                        char strColNames[][255],$ B9 R* I; D7 M: _
                        DataTypeEnum iColTypes[] )$ Q: y/ G( X$ w' z4 c* w! c
{
, E# a  ^6 a1 ]: d    try
# m$ P$ r& L( J8 b& d3 G) W- q* o    { // 参数变量
, ]. q% w5 [( Z) E" _$ r        _variant_t l_vaIndex;
4 v+ J) [  R) B; R8 ?% k  I3 d/ q7 K2 m; J6 [# L3 b# x8 \
        l_vaIndex.vt = VT_I2;
- b# o/ `' D/ a. M. A
* ~8 X! x0 K% w0 l        // COLUMNS总数+ z9 \$ y) s. d) F+ N' z
        long lColCount;
. H2 r9 d1 W$ k3 ^$ u* U- A: e; X) d" o% q5 `! k
        lColCount = ptrRs ->Fields->Count;7 |6 r) a9 B6 R6 D

1 m3 K5 N& W5 t7 n        // 循环取得列的属性和名称# [( J, h! v4 V! [  f1 {
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )6 T4 K, T' g2 E1 n4 c
        {8 w$ k% U) V" K  v
            l_vaIndex.iVal = iIndex; // 设置循环索引
) ~- \* f7 n7 q* \6 c7 i+ I4 a' K
# G9 n$ N) {2 H! W$ j            // 取得字段名称
# s7 m( X6 W% }/ f            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);0 i6 d* F4 N* W/ S
' s' r+ A) q2 h2 }/ n+ q7 X
            // 取得字段属性
' I+ \: a) v5 B: U* N6 k            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;. a9 X7 m* @' Y2 Q6 a
        }
5 e( ]: E+ Y8 \+ O* o7 B1 b; Y        return S_OK;0 ?( y2 b$ j: ]5 X. @/ o  T
    }
6 w6 R9 U; V4 a0 Q# F9 o    catch( _com_error & a_pComError ), H& R+ P( y9 b3 [  s! C
    {
( E+ u, [6 ]9 t        …. // 错误处理
  b4 j0 ^+ B/ N+ ?4 S# A5 Z        return E_UNEXPECTED;% {' y+ |2 C3 Y' G9 P$ m
    }
7 m8 y) D! T5 o) U) H    catch(...)
# ^/ ]( W  j9 z  G" Q1 M# a0 p    {
& ]% R- V8 h5 @: j: ?7 z        …. // 错误处理
( w7 p6 A7 Y+ ?# I2 m" _        return E_UNEXPECTED;
0 o4 w  G9 H$ v/ [  b    }! R7 a5 T' y. W* ]; u
}
; W5 T' K: D/ J  _" }8 d
9 i: m6 _6 X! B0 F, z& s" J* ^' L
6 h) ^8 F$ V7 t" d" `# T) L+ h6.通过数据集(recordset)得到当前行记录: G5 o2 I$ t4 y: b
  g# E) s0 x0 K' r, l$ `
HRESULT getOneRecord( _RecordsetPtr ptrRs,
) |' O( r( U- r* m                      const long lNoOfColumns,
) e0 h! x4 _" _. i0 V6 V                      _variant_t varValue[] )4 f. N0 |$ O: h& p
{
  Q2 V+ s% l. f  M7 Y5 b4 }* B    try8 D9 M$ K2 I' D, |2 t
    {2 m. S) W4 |8 @! f. T
        // 参数变量
' W% I* u2 V. I3 c/ B        _variant_t l_vaIndex;
/ T+ ]$ ~' x4 ^( o5 G' I( D        l_vaIndex.vt = VT_I2;6 [5 g( j9 ?( I3 K

& o! H& R3 ^4 |3 @$ u* P) }7 ~        // 循环取得列的值
1 p6 Q8 m) v- {6 n/ {, s1 ^+ E3 k        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )2 K) g' N$ _/ Z
        { / I2 A- ]3 H+ A, B, a- }: N
            l_vaIndex.iVal = lIndex;$ m" e( l) h4 R( f" V7 ]& \

- d$ t, h1 F& J/ t, S; L+ b: m5 C            // 取得字段值; t7 @0 W7 {3 u) X3 C. L; }- b8 Z( F
            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
7 e3 ]$ m/ W8 I1 e4 j+ B# c9 G        }. C6 F/ y9 S/ A  Z  L1 R
        return S_OK;2 C  z7 C. v6 n1 m+ x3 ^5 x
    }
' f3 v( \3 \: G' G) q7 y  c! F    catch( _com_error & a_pComError )" Q. H, \- H- ~" a1 |+ M# k& v
    {3 R6 ?. i9 Q0 Y
        …. // 错误处理
$ S7 S1 u/ w/ ?+ `- |: X# B        return E_UNEXPECTED;
# T5 t9 ]. R# W; }3 K1 {) o& D& ]    }
) T: U8 N4 L. E    catch(...)1 j! j; h; u: Q( {% K; \4 O
    {
" ]4 c8 L, i6 G4 R, K' {        …. // 错误处理9 s0 T/ @* u! e& L! c3 G
        return E_UNEXPECTED;
' U2 y1 X+ z8 i    }
! n& d; u- p6 I5 d}
6 t2 ]; a2 ^4 U3 e
+ J9 Y2 F; B% X! i$ E1 B- f6 v9 E6 {% o# R; M) _
7.出错情况下错误信息的取得0 t4 K$ J3 a: K3 X7 ]1 A6 k3 G' K
; d1 ~" l- E3 i3 c! K
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
) t5 q7 G1 F9 Y5 O{! B, ?2 R4 b- S! t
    // COM 错误取得4 Y  }1 _8 v7 k9 A) w3 y
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
7 l9 _* F/ A3 v7 B    char lpComErrorStr512];
# P' i/ ^  P2 ^4 K$ s- r- r% P/ V
1 z3 h; X" c4 e& ?0 {) L; v* ]    sprintf( lpComErrorStr512,) ~% ^2 e7 o' B( p, L
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",! w, Q+ |) U5 U! G
             pComError.Error(),                  // 错误编号
7 e: E% M& [! z             pComError.ErrorMessage(),           // 错误信息# Z7 U& o# P% O  I" I0 g2 ?: }
             (LPCSTR) pComError.Source(),        // 错误源9 [. U' z% A8 f  Q
             (LPCSTR) pComError.Description() ); // 错误描述
/ w$ H# {" o9 B1 g
8 V# [3 L* d3 o3 s# C2 c* h* Q5 I    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息$ r0 {- t, @6 ]4 C7 b1 y
    // ADO错误取得
1 ], k: S7 r) o  k+ X) [
5 O' l* J: S# R. ~5 p# n- |% u    ErrorPtr pErr = NULL;8 G; u: S0 u9 O* N# s6 k' c+ @4 E
    if( (ptrConn ->Errors->Count) > 0)
6 E8 P; r& u" r# d! n( |    {
5 c0 f1 b# {( \  O" Y        long nCount = ptrConn ->Errors->Count;0 Q, l1 G5 J6 q. b3 a
        for( long i = 0; i < nCount; i++ )4 I8 _  f7 Z! ^- G5 n3 ^
        {
7 \  q* E5 ?: l& ^6 K            pErr = a_pConnPtr->Errors->GetItem(i);
& M8 p" w$ ~8 g2 \' ~8 ]2 x- K# R: [/ |: l
            char l_pchErrorString[512];' r# k# M$ H( \; P0 H8 e$ R: k
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
4 M9 ]0 j8 m* V                     pErr->Number,         // 错误编号
$ t6 \8 s+ C4 R$ @% |, f                     pErr->Description );  // 错误描述
" O; U1 r. j$ l6 ~, N- y1 e5 _        }) c; O! _- ]8 F$ J2 y
    }
( @. `5 b& o7 Y
2 v# W- _8 i. r: x3 a    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
6 t9 d% b3 {7 @# p. b% X' V    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 16:23 , Processed in 0.017614 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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