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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
2 O$ y0 x. T" w0 p( y: M: c
( Y$ a" @; F- `1 t' d1、 用import导入ADO 的 COM 文件msado15.dll% X1 {: {! v! l; h' z

. k) ^2 T) h: j, }- K( Q# R例如:
; s7 ?  i) k" ]$ m0 Y5 c8 a
. K3 o7 D5 o3 o  R% K' H' T  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
9 Y7 c3 d/ M( n
, x: d8 }: V( E, C1 ]1 t& M0 Y2 ]   no_namespace" }! s; N0 u  a4 C

  Q9 y7 z  H' N% D
7 W' M+ m1 U: S: @  P) n2、COM 使用时初始化1 j0 \  ^- [2 [1 l. }

, b: Y9 X/ w3 d" Q' cHRESULT ComInit()# R, W9 o' L9 i2 L  s; U9 N
{
$ [" M4 @  F& l: S4 H: l: U    HRESULT hr = S_OK;             // 默认返回值
; l1 g: R0 ^1 R; w" i    if FAILED(CoInitialize(NULL))  // COM 初始化调用- f$ M6 m1 Q) T/ Q+ M
    {$ t0 o& T( o8 C% D; [# @
        CoUninitialize();: |# J: X' V* W# V1 j) Q, j* X
        hr = E_UNEXPECTED;- ]! F& Y6 I0 k+ y9 A+ @+ a
    }
$ W  N" x: j9 W0 \( X8 s    return hr;
0 Z$ _* I: o2 N& ]9 U( C& p0 g}
$ l( ?% N( ~5 D( {; k: h
* ?5 E1 p& N. F# Y& c
# G! n! p5 m9 l3、建立数据库连接# V2 L  v( f. i$ v: Q5 K. [  G5 F9 k

" u7 B1 B/ ?! `  [# kHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名8 D; j2 a, m& Q! r/ G" V4 g% E
                     LPSTR pConnString,                 // 连接字串
: [) {- L6 a/ q$ E6 C. Z/ l                     LPSTR pUserPassword ,              // 用户密码9 |$ `' z; b% }/ x, B* n
                     ConnectOptionEnum ConnectOption )  // 连接参数
9 l' P3 H7 J& p% U{
$ N; K/ ~+ w# L* O% n! }9 }$ Q* m/ j5 i4 a
    HRESULT hr = S_OK;        // 默认返回值9 @$ ^# t1 S* L8 _
    _ConnectionPtr ptrConn;   // 定义Connection对象
: p4 F" a6 R4 B. E. {( {5 j. J
0 M0 w( E; B4 @7 Y6 N  ~4 D    try
$ N/ d5 ^; g4 R. A' w$ k, b$ n    {- x) ~( Z, s# s! I/ _
        // 创建一个连接实体
5 s& T$ q; [% a. u5 e        hr = ptrConn.CreateInstance( __uuidof(Connection) );
6 L& z; S3 A6 u* G& Q% o! S
* Q6 y4 \, O0 J$ v2 R, `" Z        // 设定连接等待的最大秒数,默认是15秒0 N1 K7 f. P2 ]
        ptrConn->ConnectionTimeout = 203 Y1 g2 B! B) Y" w
' g0 X" \# ^, r) K- |3 a: d- p
        // 打开连接- N2 b3 o# Q) y. a( j( E( H" P
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );- Z7 k) Q; g7 q" N7 {
        return hr;
9 d7 {6 d# A; p. x    }
. |2 N1 {8 L9 c; x2 @    catch( _com_error & pComError )
4 g5 v, k6 h4 J; s* E0 Y    {; E/ `: k% I" R) A7 h
        …… // 错误处理. t: i0 K" X9 k' y' m9 I
        return E_UNEXPECTED;" V- ]7 G, q' V  X$ j
    }
7 g: k/ b" N: r% G3 T}
7 G/ k) f& e7 Y8 D
6 j6 i. R% L; Y% i' N& c$ }2 P
. v! N5 U1 c# u' J0 A" ^0 n4 o4.执行一个SQL 查询,得到数据集(recordset); G/ P: w& d& T

2 Y6 X5 M9 b: Z. e! p2 q_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
, i1 m( F! {& W; w* T8 G{- i, b/ x# O# A+ |" t
    try( i1 M) o- F9 k7 ?( j
    {4 y6 Z! S% r# z$ M( \5 q* P6 \; _
        RecordsetPtr ptrRS; // recordset 对象% j7 C1 k# Z5 v; n$ q- l+ W

/ l% A; l1 P* E1 A' e4 c        // 创建recordset 对象实体
" ^: [' m' e0 G0 e8 U        ptrRS.CreateInstance( __uuidof(Recordset) );
6 ?5 y) i& B: v7 }# u) t0 \        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
/ @! Y- a7 N' m6 o6 P; U2 ^adLockUnspecified, adCmdText );1 p/ H+ ]% Z& w1 u+ D

6 H! e8 }6 V4 z( j9 J        或者% B+ c  u+ D. b' K( U
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );- I3 l1 D& c; Z
        return ptrRS;5 l8 c- ~! v  l4 y" B- R. K# [  s5 H
    }
7 ~* u5 z+ s, P) W  c6 E! m    catch( _com_error & a_pComError )3 N9 x- D5 {6 }  D8 p
    {0 k3 O& b, T3 h6 G3 p' a# t
        ….// 错误处理
. x9 T4 A3 ^1 y. h8 G2 y        return NULL;" W- q* I) ~" e4 N( K9 \
    }
: B9 f6 u8 d/ A9 [}. D( J; k7 v) p* a9 ]# d

7 B2 j( b# I7 U$ Z* T% P/ y8 O  ^9 n) W1 W! b5 b
5.通过数据集(recordset)得到列的名称( r4 M, ]" Y' T' p2 N

4 C' @6 a( b3 K9 N: M1 |! UHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
1 L5 r6 l6 w" ?5 O" T& d( _# \* A                        char strColNames[][255],0 S# J/ R. [  g8 ]' a* Q
                        DataTypeEnum iColTypes[] ). F" A3 s  M2 Y7 `9 b9 {
{0 |" G# y( |) H. ?3 S
    try
8 ]3 R: G# `& t& W5 J    { // 参数变量
6 ]- L* @/ w2 h" J! k        _variant_t l_vaIndex;, H/ `3 g% e! }3 A5 ]* S, W0 z
/ ?: j% M% M; X! ]2 v
        l_vaIndex.vt = VT_I2;
1 G4 v7 q) g) ]
+ Y; t- M$ M/ e' i9 J" d; e        // COLUMNS总数
* J4 N, L$ b! ]0 U" `6 t        long lColCount;
' y$ |  d/ k6 v+ z/ d& ^
' P, x" ~5 S0 {0 D5 w& B& k/ C4 q        lColCount = ptrRs ->Fields->Count;+ E! G4 {% S: \% ^
2 y( R- E3 _$ o' J! B9 s" {0 b
        // 循环取得列的属性和名称$ J2 Y" x" n5 w/ v  n( P' @9 Q
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
# X" D" i# x: T! h* S1 M        {
6 v; m9 h5 j4 H9 L            l_vaIndex.iVal = iIndex; // 设置循环索引
3 w: }# H7 w$ }& X3 ~) M4 w3 n  V- E; ]6 b
            // 取得字段名称6 L6 A! v/ A/ L
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
) ?5 |6 N* v) x8 Z! c& ~* f/ @
& _& }- X, A2 Q; a0 p( r1 E            // 取得字段属性1 F# k/ F- ~2 U& s; w% T* G
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
; Q0 H8 U, Z/ N  ]+ _2 w1 C        }
6 z. F* v2 X, a6 P        return S_OK;
0 m6 ~: r( A1 c& B" P    }
! g! S- _6 B$ n' M# W  d    catch( _com_error & a_pComError )
( ?" J6 t* x* ]; f4 h4 W& J' z/ J) z    {7 W8 X: D; _2 E  g8 Y8 _# z( m& t
        …. // 错误处理
% d3 x' y# Q4 {  b! V) h/ U        return E_UNEXPECTED;8 {  l: U5 P' v# L/ o- N
    }
, I  U0 ?. x6 _) u    catch(...)
4 I5 ?$ ^1 T! ^) J7 ?8 W' t    {
! z' M: `; O1 I! u, J        …. // 错误处理
4 ^6 b6 h7 E% m4 A" g  F" c* g        return E_UNEXPECTED;
+ A3 c0 Q# E! A% ~9 f! D$ j" ?    }
& U; p) @' {" W; P2 H1 `' I}
5 b. t5 E( Z4 ?1 l* j0 P
( e9 x. Y+ P9 W; E6 v
2 k5 t# L4 @8 U8 P6.通过数据集(recordset)得到当前行记录& d# ?; X4 M9 E2 Y$ h

! f5 g# h# Q7 T. t% t- ZHRESULT getOneRecord( _RecordsetPtr ptrRs,9 G- H( `: U* A
                      const long lNoOfColumns,, i7 |1 M& F  Q  H
                      _variant_t varValue[] )
7 [$ Y  I2 J5 }; d# k$ ^! ?+ s* `, Y{
7 `; A5 |1 Q- Q6 y* i    try
# j( o- n9 Y) s    {2 D3 d( z; G; H( e  i% t0 U, N) ~
        // 参数变量
& S$ L) t# a: o( p+ ?4 I! K        _variant_t l_vaIndex;; E; l9 f( a5 G9 t$ {0 R. k
        l_vaIndex.vt = VT_I2;5 u  ?( w* u8 X2 f( R3 b
7 N. F1 R& i1 T
        // 循环取得列的值( j; J# o( F4 @0 ^% b( M0 J
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )5 G3 ^0 Y/ f* y5 l( o9 Y
        { " P/ X, G  o6 i- I& a
            l_vaIndex.iVal = lIndex;4 T7 a8 a0 r! {' L& Y

! r1 e5 T% q& j3 d            // 取得字段值6 g# O. ^2 {0 E  ]/ k8 h  G
            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
2 S# j& s7 C) E6 g        }& Z8 L( M% Q0 y/ C. \9 ?& \- T
        return S_OK;9 d4 |6 {! ^9 _
    }
1 W; C: a0 D% U" Z0 [* V) L    catch( _com_error & a_pComError )
0 f2 L- ~* ^$ K% H2 J6 S    {
' c& @0 _8 a! J" Z        …. // 错误处理  M. g$ {: b5 h9 w( B: G6 E
        return E_UNEXPECTED;
; l( B" o6 i4 N    }* j3 g7 w# a( s0 j) x7 |3 g
    catch(...)
4 w- \5 D0 C; W7 X; P3 E    {# S/ ~# k9 v# u+ z
        …. // 错误处理' B0 o# [3 }9 z$ Q1 P
        return E_UNEXPECTED;, R3 e0 v2 i+ ]; q+ r5 ~
    }5 L$ j) J6 ^! E- ^) ~/ m/ L; |
}
! w, Y) w; |8 z& ^7 L
: N! }/ M3 G) X$ G2 J8 c8 O' I: ?, W  o
7.出错情况下错误信息的取得& p7 x! e" \; O1 J

" O: w( F- b2 Rvoid ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
9 y0 o9 |- Z! w{
' P4 L' \$ @% f; e- u! r    // COM 错误取得
: t0 k& f. d. J  e8 B    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常" Z1 a6 n" p- T4 G
    char lpComErrorStr512];; L* U" K9 l* \! N3 T( B

6 v! g5 _# \& ~    sprintf( lpComErrorStr512,
! i- y8 V7 E% F% Q+ N/ B  l4 G" m             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
% J7 R# p& B2 O  ~' s8 V4 E5 R             pComError.Error(),                  // 错误编号+ E: M' S6 i3 p7 ?! p
             pComError.ErrorMessage(),           // 错误信息
9 [/ T6 j6 S8 Z+ O. K7 R             (LPCSTR) pComError.Source(),        // 错误源
* K" ~8 [6 p3 U/ \             (LPCSTR) pComError.Description() ); // 错误描述
; p2 J& l8 ?1 T9 Q0 D- n6 ?  ^3 P& l4 L7 G# a- d
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息3 w, }; v1 g/ S+ P( \
    // ADO错误取得
4 M7 r, _, U  H: h! F% y& ~7 k4 f' |! h  A0 D. f( k
    ErrorPtr pErr = NULL;
: X5 X9 o( X+ s3 c. ~/ }    if( (ptrConn ->Errors->Count) > 0)
/ R; c. \! |  r! q! S# f  c* C$ ?$ E    {, F/ }6 }5 s) [' \! x) h
        long nCount = ptrConn ->Errors->Count;2 k  g; |; ~0 Z; K. x. b# _5 R( l
        for( long i = 0; i < nCount; i++ ). X: g! q" E, t% a% h! e
        {# _+ m! d, F% j$ }% x0 E
            pErr = a_pConnPtr->Errors->GetItem(i);1 I" x* o' k8 y
/ e2 c8 }# i, C
            char l_pchErrorString[512];
4 t- R0 F  W( G8 a( {; F. n            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
1 ^7 ~) z8 d$ V) w/ r                     pErr->Number,         // 错误编号
) ]$ Y% ?2 q5 e0 Z                     pErr->Description );  // 错误描述8 H8 L$ C8 N" v7 X# I: F' q5 ~
        }
7 l' j  n6 _  L% ]5 p; P    }
" P5 m  m8 {5 I; |- R) ], O8 L1 _5 W. [' }3 e2 w1 d
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
1 k. T+ v1 ~3 {6 C8 e7 V) a    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-13 21:35 , Processed in 0.018407 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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