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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
  k- ?4 \1 m. o# c+ k, w/ W2 F( y* }/ h: G( V. d$ e+ ~1 q' s
1、 用import导入ADO 的 COM 文件msado15.dll  _' V4 ?3 x: x  {
( H& O& z% [$ X
例如:/ y6 W0 T6 w5 l$ E2 B( w

+ u7 t. t2 {4 h7 J% B  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
! f+ r! t# Y  B' I: |3 z7 K0 Q9 A- L" f# ]: h7 v3 g/ b
   no_namespace2 M% ^+ ?, C# V( b1 t8 F6 F& S7 n- H

, J' V  C" l! s  T* v( a; {. A' z# R
% n) k, {( T& u/ I& G2、COM 使用时初始化
. a( W8 W3 q: @2 @7 x! U
$ Q9 n+ k( l& |& x" gHRESULT ComInit()
" g. {& |+ B! U" k{
9 i/ o8 \; L% ?0 a7 V8 K, x    HRESULT hr = S_OK;             // 默认返回值
5 u; z7 t' n$ k, U5 [    if FAILED(CoInitialize(NULL))  // COM 初始化调用- J" O5 a# Y/ k$ f# Z
    {( `6 k" Q% ~" r. ?9 |2 k/ _
        CoUninitialize();
: l2 T! i3 N  G+ `, ^        hr = E_UNEXPECTED;
1 X  k6 H2 F" I8 `/ X    }9 Q  q. Z- B3 k  p) g% q
    return hr;
/ t6 g: M# G; |}$ [- K2 A7 B& m2 X2 |  ~; w3 u
/ Q) }* N5 w/ l  U

0 M: C' F- [( Z3 I5 \' e% ?3、建立数据库连接4 Z: M1 L9 l/ o

8 E* b8 }- z; s( UHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名9 n0 ?( C  D$ f- H! \& S
                     LPSTR pConnString,                 // 连接字串
0 D: y5 Z  R. u$ {6 c) D8 F' P4 U                     LPSTR pUserPassword ,              // 用户密码
. D) h3 B, b/ d5 d/ {                     ConnectOptionEnum ConnectOption )  // 连接参数1 X/ Y1 S3 o) _9 E4 T
{7 @1 P- b! E* U

; e/ L+ Y, i% P: m4 V    HRESULT hr = S_OK;        // 默认返回值# [1 {' \$ o' U1 D4 B: H
    _ConnectionPtr ptrConn;   // 定义Connection对象
" y- ^" T8 Z1 D( ?$ N9 B7 i
7 o+ j( l# o6 b; n7 w0 A    try
/ `6 j7 ~  ?# c$ S: D' y4 X  x    {1 k$ |3 f% j; i8 u. l' O
        // 创建一个连接实体2 C9 l$ L: y- @7 I( N2 e
        hr = ptrConn.CreateInstance( __uuidof(Connection) );
$ o0 L# ^, k6 R+ T+ J3 v4 c
3 f0 Z: R; u& z4 k" T        // 设定连接等待的最大秒数,默认是15秒" A* W$ n% B* S' ^/ [& K" m: I: ^
        ptrConn->ConnectionTimeout = 207 n9 C% m4 I/ E+ E( {2 L
5 o7 _  i0 Z( a) S) @9 Z
        // 打开连接
) h3 _* s0 F8 I) b( V: y        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );7 M1 K) ?( n' E( B
        return hr;( k4 x& u8 ?$ n% T2 }
    }
& L) w8 P% R" K* n    catch( _com_error & pComError ). t. C6 O5 x( X9 x0 X. D7 a/ S# H0 O
    {+ A5 ^: r4 S- M2 p
        …… // 错误处理
- E3 k0 x7 G: z# X+ a        return E_UNEXPECTED;
; F8 i& F9 L% W; A. C    }9 M; s) C: Q$ _4 ?
}
, a; v3 y0 e9 z5 N+ D% D3 V
+ \# u" ?  S7 ]- C
$ b* ^8 o# Z6 I' ~% u. O1 {* i4.执行一个SQL 查询,得到数据集(recordset)9 Y' m0 ?& a/ x5 p' _

& F; s  n5 G" P8 K8 }_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
  }$ `- }& {# Y: o+ Q{
9 G, H$ W& g0 |7 U+ O    try8 p. g8 i5 [+ {3 z
    {
+ s0 x1 Y; D  {4 k  T2 s        RecordsetPtr ptrRS; // recordset 对象
7 T& X- a! T8 m2 y! |) ?4 H* b
0 V+ r) k% e) D1 \. V        // 创建recordset 对象实体
1 [7 u2 i' ]/ S2 N" H8 F, e' R        ptrRS.CreateInstance( __uuidof(Recordset) );
, f& }1 W3 s5 t: x) f3 @        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
7 L% C( N- X5 V& B, |( iadLockUnspecified, adCmdText );( ^+ Q3 Y  t8 i; Q% H
; Q8 {% a6 y- k, x: V
        或者1 t# C! i$ F& X1 V0 ], b# @+ b  I
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
: w% @) @7 V8 ^) b8 T, a1 P        return ptrRS;' Z# s4 a6 Z! n0 U3 I# |7 u# R
    }
! u+ P. Q( g, X( l, |    catch( _com_error & a_pComError )
4 j4 F$ f, `* m6 E' @( r    {2 E6 A5 i+ Q5 [' c( ?# w" t1 o
        ….// 错误处理, b2 b/ |6 I( Z1 D7 _
        return NULL;
1 A$ [* q1 c8 l) m3 X    }  ?% t9 Z- R$ e) i' a, ~
}
: {! k7 k& R0 X! `+ A4 N
2 Q, X  [6 D4 C: G9 C+ v3 E9 ~; i0 ~* Y# F$ \. Q0 \% [5 j. Y
5.通过数据集(recordset)得到列的名称1 r; Q! _+ T* G" [

, Q/ L- {, Q' NHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象( _5 M: Q( C+ v0 S. V
                        char strColNames[][255],
$ }1 y; N9 ?" X  h                        DataTypeEnum iColTypes[] )
& W% ]( @4 [* r6 j" R{
- V# l! H0 o2 H. F/ F    try
# |4 Y) o8 m6 q$ K    { // 参数变量$ ]) }- Y* J. S3 D/ ?" G
        _variant_t l_vaIndex;/ Z2 _7 p; [" s' ~+ m
$ F) ~$ |2 C- F8 T# x+ i
        l_vaIndex.vt = VT_I2;
5 d/ p" V: z2 h8 U6 U: a
: t' t) _9 p. k1 ?        // COLUMNS总数
5 {, K( s4 O/ @6 T- i1 Z3 P* E* }        long lColCount;, V( V2 ?( |& t+ ?! _

& F4 h7 {/ q7 O" @  Z        lColCount = ptrRs ->Fields->Count;
, {; t. s( r! b) P0 f1 d
( E# Q4 w+ l2 N        // 循环取得列的属性和名称6 Y. k9 g# |& L  |0 Q- K  [
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )3 i* U4 q* P, d& W* ^1 x) l+ t1 A; G
        {. Y4 }" g4 E- {# f+ U, L/ B
            l_vaIndex.iVal = iIndex; // 设置循环索引
$ J  `9 _1 v  J9 ]* z" [0 x- A. r4 i! G0 {5 |
            // 取得字段名称  O- M' S& S3 q* [; a
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);! c" D3 O! }+ _3 E& n9 t; |* R- A
+ ]/ o: l% [# y( ^- U! X* z
            // 取得字段属性8 v3 U! q. f& L  I7 b0 W8 g+ d* W
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
- U+ A; Z8 `8 y* L2 B5 y        }* }1 c' L6 l* P6 L9 F
        return S_OK;
: @+ p7 |2 E8 R3 N& r$ h; ~    }, C5 {6 Q, c7 s
    catch( _com_error & a_pComError )& T: ?; Z" \; T% j4 x$ w7 a6 H! k* M
    {4 y% o9 q: A# z( B; y' e
        …. // 错误处理
9 P' {5 G* O  Y8 W. @7 c( l        return E_UNEXPECTED;6 i1 H. V9 ~" l/ \$ f
    }
: ]! I/ S9 ?  R% Q, e$ [& W, }( ?  _    catch(...)
! k& g6 }7 d  G( u4 y, ?: G    {: u2 c. Z/ W3 T8 a7 S* |3 i7 D
        …. // 错误处理
; T; x/ M& n% V* @4 m+ ^        return E_UNEXPECTED;$ |) w5 h5 B& I$ V
    }
& l* \5 r/ j1 P# X. i}+ i7 M! F- a% T

6 R, f" h# b; I3 l  l$ X% {3 f( U9 W+ j2 ]
6.通过数据集(recordset)得到当前行记录
+ H9 s! ]4 E" G3 \( I0 s
3 w) a  I# Z0 ~( z5 W9 x' K4 JHRESULT getOneRecord( _RecordsetPtr ptrRs,
$ f. M" l6 n# I. M7 e; I                      const long lNoOfColumns,5 ?) G9 n; b3 C
                      _variant_t varValue[] )' e9 t! f7 ?: O
{  H/ i3 H) i6 d3 F
    try9 T1 R# I: o1 \) k
    {
/ r/ `& C4 E! \7 V9 _        // 参数变量- M0 f' C) E# f
        _variant_t l_vaIndex;7 B( ?! p  g: [) T3 k0 d/ k' D
        l_vaIndex.vt = VT_I2;
! V* `+ U7 }) \8 ], g3 n0 _/ y9 R9 `& ^% A4 c7 V3 F
        // 循环取得列的值; g6 \0 G7 A7 `1 ]
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
! ^3 t9 \3 b) c" ^5 P5 `# ]9 ?1 J        { " ^" U$ T4 B3 u0 ]0 f. e8 P5 q/ A
            l_vaIndex.iVal = lIndex;
; L  X$ f/ p4 o* W) u/ b  ?3 ^- z2 w4 R% P
            // 取得字段值' x; U4 ^% [! H! X( v8 L
            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
  m( ~& I. s5 B9 o) z4 S: t- }        }
" F$ b  @. c7 e. z$ s1 g+ d        return S_OK;: J, W. a4 O/ V$ ~
    }* y4 P+ X2 C* e% d7 |7 y
    catch( _com_error & a_pComError )
& |& o5 I! O; q* C8 ?* K' g4 o% M4 O    {& n; _1 R; a8 R1 \2 m( H6 `
        …. // 错误处理
3 ?, m0 |  c$ s1 w5 J. z        return E_UNEXPECTED;' ~! W, w9 o( b7 C
    }
' q2 @4 b! B2 @3 U    catch(...)
! z+ a5 E3 G% n% u6 ~( |* n    {
# c2 C9 i% E* a5 r- ]        …. // 错误处理1 \. E( c) Q5 v
        return E_UNEXPECTED;
4 B, Y3 n  P5 {  L+ a3 Q    }
3 n- S) A$ D; b}8 ^1 ^3 z# x( P2 K  G7 Q

( Q# l' q0 y+ S5 ~: o) U) Y1 V2 ?
7.出错情况下错误信息的取得! _  o4 P6 m% T  e- c

. ~1 `" A3 A4 n! R" w, ?void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
) V, C7 y; \8 J- I" e{$ {8 o5 }+ U+ A+ n/ M
    // COM 错误取得
; I) v' F+ T( ^/ x    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常4 T! k$ d/ Q( N* N- ]' y
    char lpComErrorStr512];$ q9 |7 l& M* \0 I# ^

: O( }& N) B% p( k    sprintf( lpComErrorStr512,# d; j( y3 f# @
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",1 T3 [0 s! {3 E/ \$ h2 i! r) _
             pComError.Error(),                  // 错误编号  F6 e+ ?4 Q. q) R6 y) g" Q
             pComError.ErrorMessage(),           // 错误信息
. w# N; E4 `* o3 i             (LPCSTR) pComError.Source(),        // 错误源
0 X. J/ l8 e8 k+ C             (LPCSTR) pComError.Description() ); // 错误描述/ u, l! T. I- z. [+ H4 S2 o: y
: Z4 R0 A( K0 m3 ^
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
" G. M+ t' r$ v- |, A. E4 E    // ADO错误取得& X; Z" B' V6 C% h# M9 U

9 y$ w' e9 ?) h5 l4 B    ErrorPtr pErr = NULL;
7 S9 }; m: z: K4 f0 t8 N* r. P$ c    if( (ptrConn ->Errors->Count) > 0)7 L5 H6 D( [2 j8 z+ B5 \
    {
1 _# T0 D5 S) H        long nCount = ptrConn ->Errors->Count;
; h. z- P8 z  j  x$ d: c1 ^! r; @        for( long i = 0; i < nCount; i++ ): O/ O8 {1 h7 ]
        {
* R! f: x) |! k7 `  s$ u! @2 `) p$ `5 r            pErr = a_pConnPtr->Errors->GetItem(i);
7 `1 i  ?4 z2 w8 e3 `# s+ N! _  P+ `% V/ {# j# k& A
            char l_pchErrorString[512];' D- I" S, Q8 [
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",0 @# g- j( ^. p# P
                     pErr->Number,         // 错误编号; [4 |  N, K% q+ D2 X
                     pErr->Description );  // 错误描述
, P; P) U8 J2 S  X; u        }
. q! S  H  Q$ n    }
3 a) U4 g, p! e7 v# F
7 K- P! k. Q, q) O! r    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问4 {( M* ?2 t6 |5 v; e
    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-11-14 19:56 , Processed in 0.021273 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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