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

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

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

! f& W* x' t- z1 `2 ]* Q0 B& S' @" C1、 用import导入ADO 的 COM 文件msado15.dll
8 D6 l1 F/ n& x; \0 I* L' J  M$ h) |4 z
例如:. Q6 a3 l1 t8 L1 u7 D, z5 P7 I, P+ o

- q; _( z/ p! g7 m7 n0 ?2 g  D  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
4 d  x! o# `. q, s& ^, t3 L% _, Z: E$ f% a  C
   no_namespace* F# x; y. f2 b1 ?$ k" B
$ I2 p3 A: @7 l* ~+ D
9 L+ R: b6 U7 }6 g3 J
2、COM 使用时初始化
! M" I5 l, V7 X4 L# P+ l$ k1 ]* Y. D4 `' @
HRESULT ComInit()# A0 C# {2 V: u+ D3 z
{ . W/ q2 ^5 [. y! M6 f
    HRESULT hr = S_OK;             // 默认返回值) g# P4 k4 _7 |+ Q
    if FAILED(CoInitialize(NULL))  // COM 初始化调用% A  _* f" J8 s1 C; L
    {$ R3 i& P; f3 S2 ^; V' }9 g2 I
        CoUninitialize();6 k& ~. U: l' {
        hr = E_UNEXPECTED;' C- o2 x* `$ ?
    }' }3 ?4 }/ S% j- o, P. s
    return hr;+ f" z( e5 }! F# I
}  R! c0 v; }( @" b4 V/ H* k7 h

& ]- p- M" `9 O, u
$ ?0 v3 l8 w6 }) y3、建立数据库连接8 n. l& J  }, J1 w1 ]% `  Y5 U3 i
7 \8 z, V( p/ m# ?: Q
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
# [3 z4 t$ F7 S9 C3 D+ V                     LPSTR pConnString,                 // 连接字串 & y& n% K  V6 r
                     LPSTR pUserPassword ,              // 用户密码6 k4 g0 f! Z1 a* S% F- o  E
                     ConnectOptionEnum ConnectOption )  // 连接参数
2 q  ?4 k# i3 w; h{
5 Q7 y7 N( G8 k. h  [; ^- Z, m6 u( p; U4 y' y  q  c
    HRESULT hr = S_OK;        // 默认返回值
: B+ ^: J+ W- B    _ConnectionPtr ptrConn;   // 定义Connection对象
1 F# `/ `9 F5 F  a
% e3 w: M. ^( b' B, A% S    try
- e! w  f. x. P) i- D$ N    {8 V5 t; _  j# x/ K, a3 E
        // 创建一个连接实体
4 u+ [* O/ H7 w        hr = ptrConn.CreateInstance( __uuidof(Connection) );7 n7 H& d% b) H* O

# l2 q# [$ |. {# O* L        // 设定连接等待的最大秒数,默认是15秒
" h- L6 S; Y; j        ptrConn->ConnectionTimeout = 20: Y/ ~* t7 G  C; p' c2 ~
1 ?. c+ l$ {7 v% M+ c1 X% u1 ^
        // 打开连接
0 H6 H3 v: b& A8 g# N        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );7 L- U6 {) W. T6 o% Y' C
        return hr;  v  N) ?. y+ h
    }
% y. f  P5 |6 f# c    catch( _com_error & pComError )
3 J6 q' p' c2 u6 B    {
2 T) Z& L2 D& d0 J+ B/ _! q1 H* w7 A1 b        …… // 错误处理/ `! r! W3 J  |$ p; T# V7 x; c6 G
        return E_UNEXPECTED;) t7 s1 F$ G( e) C% y  f+ n0 I
    }
, I* `1 J9 S/ ^}  j8 h9 r0 @- `
; R' T7 _5 H! g! Z$ z

% a5 q7 X/ G* a8 y; Y5 U4.执行一个SQL 查询,得到数据集(recordset)
; `- p9 }' r# X4 O, z- S& }/ N) T$ W, Y4 f+ K2 j
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
/ h" L1 [9 P0 d* ~4 i3 k# V- Q{
; o3 r, r# u1 W( \, y* |' D    try
8 M5 ~! ^# Q3 n8 a5 X" r7 F( @    {
5 W! t4 l" u  X. J' b( V        RecordsetPtr ptrRS; // recordset 对象) G" V( }5 @# ^) i; m3 w" t

0 m+ f& e. T6 X( z9 s4 S3 o6 b9 Z1 t        // 创建recordset 对象实体
& J. H3 h" N( b0 z& d6 d        ptrRS.CreateInstance( __uuidof(Recordset) );- |2 ^9 l- n* I6 m' H2 ]
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, 0 ?. g2 y$ d$ m6 P5 p
adLockUnspecified, adCmdText );( J3 ]& _# ^& o: R9 O

$ n, o4 N, S9 H& u; U4 o$ a        或者, R$ k( Q9 o" x
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
8 X& `3 L( g, e! m        return ptrRS;
- M; n( Q5 ~7 f+ M- e1 S    }
; Q) a+ O( O/ O    catch( _com_error & a_pComError )
, ]6 W) X8 Z" }- B. h: B    {% M4 T6 z& T1 C
        ….// 错误处理
+ X9 l. t( I- N% M6 E! W- a        return NULL;
1 M9 Y. |' w) Z    }
  L( ^- F6 M4 _  V! X4 D}
$ K' Q. j$ D8 n$ F7 \: C" R& y; Q. ?& Q0 @6 y; }1 K

( x, i, d: D' w  R2 O5.通过数据集(recordset)得到列的名称7 U& F0 }8 P% l( n% Z
5 z0 _: m2 Z& b
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
4 G! f4 G/ z6 b7 v4 P1 c" J+ c                        char strColNames[][255],
, i& }5 I' M: M% W3 H; Z1 h! J                        DataTypeEnum iColTypes[] )! |. }. r8 D- o  G
{
: V6 E" N3 F# u% d    try; r* [/ U& S$ u3 c
    { // 参数变量
. c* z$ r9 _1 ]6 r& j' P        _variant_t l_vaIndex;5 t0 I( a# u1 U1 o. I1 F# T2 s
2 g( @) l; Y& M
        l_vaIndex.vt = VT_I2;6 E' n: Q, k( E. O4 i  ~. r

- g/ A7 r  V9 o* _& }) Y        // COLUMNS总数2 P( K- t, |6 f# |: Y
        long lColCount;$ _" b* \/ M/ K  W$ p& w( D

8 w8 |3 V/ ^( T- }, ~        lColCount = ptrRs ->Fields->Count;
, ^; w2 `6 F5 Q' k9 b0 ~4 j2 {5 }! [, V& g  W  M4 W& a/ [1 g# i
        // 循环取得列的属性和名称
- Y. C4 k$ v0 w! |$ m        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
3 Y" ~8 J/ u7 |) Y* H        {! I) z+ R1 j! h( ?) y* ~
            l_vaIndex.iVal = iIndex; // 设置循环索引
# T1 Q0 m9 _, i: q/ k3 v# u' T7 ]" R) {0 i% @8 p
            // 取得字段名称% e3 v9 J  R& X0 ~0 T
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);6 }! o# L# ^3 j/ |+ f: X

$ b0 o5 w$ I$ C$ p9 ~" o            // 取得字段属性
4 ?( {$ T/ E( N) `0 Y            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;. a* A5 B7 q  }7 ~* M0 R% `# `/ B
        }
# `/ z4 W/ \5 o' Z0 k2 z( Y: ^        return S_OK;
2 }! A0 u! J; ~: ^- N; r1 m3 T    }3 M; Q7 E2 o3 H7 w7 e4 A' L
    catch( _com_error & a_pComError )
) S" h- `/ A0 {9 U5 N2 o    {1 V8 ~! Q7 O4 J) g7 ~
        …. // 错误处理; a1 f+ X( L" x
        return E_UNEXPECTED;6 ?. B; c7 u8 k, M
    }& ^$ H  M, l) `; T8 e: v, D
    catch(...)
: m4 q; N; S- w. _    {
, Y6 k4 P  v( k; q% ~& E        …. // 错误处理4 L: T$ d7 b6 Q" f0 L# X
        return E_UNEXPECTED;
( k- A/ v  R  K2 f7 ]7 n, p* F    }) u9 c0 G2 V9 g: a8 I
}1 G1 e- `' Y3 R' U' |

1 Q0 M7 P! g7 j3 {1 K4 q, b. v( y% z  e5 P( E5 j- m0 `. \9 L
6.通过数据集(recordset)得到当前行记录9 o4 k% U0 x# M0 d8 c# C; R

, |& x$ v9 p- p3 nHRESULT getOneRecord( _RecordsetPtr ptrRs,3 p9 n3 f3 w2 S* ?- s5 D& l
                      const long lNoOfColumns,
# C' m% k5 T% i                      _variant_t varValue[] )$ _) a) ^- @  ]8 L5 ~
{6 x: s) Y8 R. m. A# N& o
    try! ~* G, c' T- [2 ~3 s. `! _
    {. O$ h% P" H7 ]* a
        // 参数变量( G9 C" h9 ~0 J! ^! `
        _variant_t l_vaIndex;
" V3 d! f" [9 C& y6 H" T  s6 X        l_vaIndex.vt = VT_I2;
: J0 w. O- W' ^  Z# w; i* q0 C3 `6 Z  _  e$ x% D
        // 循环取得列的值
: o0 \7 E6 _. R8 b+ ]3 E! J2 `        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
! D& S; z3 F/ l4 ~$ H        {
1 u, L& a% t5 |% I) \! {            l_vaIndex.iVal = lIndex;- r6 ^: r, R  u: p' Q- s
- q2 d8 ^) N7 q4 J, _2 S
            // 取得字段值
( y7 j1 R' c" y% G- b( M  V% x            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;% y5 z) |* @% Z3 e. E! N' o
        }
1 b  g/ H8 j6 h- @        return S_OK;' Y  c% a, ~, M. o) i' g
    }7 F1 L0 J2 j* T- i) t& }/ i; U
    catch( _com_error & a_pComError )
* e& b5 C( _$ p* }& Q5 B4 y    {
$ j) j2 E0 Y) o# ~, n        …. // 错误处理
: Y" F- J& j& b3 [& w        return E_UNEXPECTED;
6 f- g+ b4 ^! v3 o    }& w# I. ^! i$ i; D
    catch(...)9 ]. ~1 @" M, v
    {( f' U6 Q6 C6 l* C
        …. // 错误处理5 E* S4 ]- Y; e; K2 X- ?8 o$ c
        return E_UNEXPECTED;
8 ?. [1 e! k9 C5 n    }7 X3 L. u6 s. ]) E
}
. ?; H: x  ]- [7 L. D7 ^0 m6 V1 a5 a  M3 \

$ _& Y$ Y: b, c" q7 r7.出错情况下错误信息的取得
$ |9 o) m% I# ?- M8 W! F) P$ K- k' r! O+ L$ ?
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );1 r  v! c) B) `! [( R( h
{9 ?+ I- j) \$ S- D5 X* i8 Q
    // COM 错误取得
9 [4 W5 B, c4 Q0 h    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
. W# k' g) O, T" s/ Z    char lpComErrorStr512];/ ^% w; e1 P9 U$ D/ Q

; f' m  {+ ?/ j( ^$ S    sprintf( lpComErrorStr512,
$ m5 u3 q; Y5 _. w             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",7 @, u( P9 q4 l) d
             pComError.Error(),                  // 错误编号6 _+ j, Q. x; T. z
             pComError.ErrorMessage(),           // 错误信息
0 c% u+ H7 o1 l             (LPCSTR) pComError.Source(),        // 错误源4 L7 T/ W: N: E: U
             (LPCSTR) pComError.Description() ); // 错误描述3 J5 @9 a8 g" `2 H
- X8 x+ d/ Y2 C! [, q, J; H1 I
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息* o; x' a/ v! k2 E
    // ADO错误取得! k  U/ o6 i3 |4 c% _& U

: v1 w& @4 L2 |$ H! {" c0 ?; |  b0 z    ErrorPtr pErr = NULL;) Q, Q5 H" p7 E. n9 k% c
    if( (ptrConn ->Errors->Count) > 0): m  B% u8 }* }! J) O
    {0 @. j, |' B$ G5 E% ]' [: }& L7 T/ A
        long nCount = ptrConn ->Errors->Count;
7 \& k1 |' O# n- s# `        for( long i = 0; i < nCount; i++ )- e- ?# p3 C! a9 x& A. d9 d/ `
        {$ W  O- C4 d+ P5 T" e5 ]4 v4 j
            pErr = a_pConnPtr->Errors->GetItem(i);
/ l7 Y! |# _( }4 x- x$ `
' Z& n/ |! w4 b" g$ O            char l_pchErrorString[512];
) ?6 ~$ ?1 ~3 r- w, f% o' L            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
: K- R1 ~( o0 R: [; a. [- c                     pErr->Number,         // 错误编号& o0 C! N+ E, p1 b9 [( O
                     pErr->Description );  // 错误描述
* h2 s$ k0 `* T4 j- b        }0 h5 C9 @) ~  L0 x8 k( R  u
    }
7 l$ }# h! X% ?+ \7 e
* p4 ?3 g  ^& m    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
7 K4 g& y4 K! {" D* y4 v    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-10-2 00:12 , Processed in 0.017533 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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