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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
9 [! Y6 Q7 M# L. \3 o8 U8 _$ g3 a" g2 _: H0 p4 p& V1 j
1、 用import导入ADO 的 COM 文件msado15.dll' ?% O& g1 b* ~# r0 L

& G6 m5 y/ R' F7 i# P例如:* Q2 P8 U& U; A$ B
1 f+ c, Q/ k+ Y0 N; C
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
. V1 A+ u/ v# C9 l+ e. y3 [7 \8 g8 L( U' |4 L4 J% L
   no_namespace
& @, r! @; f$ E0 l; X( G1 L3 I/ r. t9 r  p, {8 }" x% \

" U! `5 c# @" ^2、COM 使用时初始化
' `' e: o4 C- ]7 y+ Z3 c% ]
  Z9 |% Z+ E4 N% A0 C7 }HRESULT ComInit()) I2 @$ D- k& L  O' h+ a! H
{ 0 I' Z7 d& }5 T
    HRESULT hr = S_OK;             // 默认返回值
1 ?$ n' T, `! {6 D3 h( C    if FAILED(CoInitialize(NULL))  // COM 初始化调用5 H. k% W! r% K
    {
& W, p" c& q3 K8 [# P* F3 _6 _        CoUninitialize();
# ?8 Q0 z6 v: k7 J3 `9 z) j3 }        hr = E_UNEXPECTED;
5 x  T! B  k2 _6 q! ?* d6 a# ]4 M    }
, @/ c2 I% [/ ^- b) @; D% J    return hr;# v6 t# w; m% N7 S/ k
}$ R9 b: A' q1 {/ X% h/ [  }3 P
1 h9 k1 L+ X- Q8 A8 k' Y2 s
  Q% n& V4 l5 _
3、建立数据库连接- y- |) d6 j' x' p  b8 W0 a

: t9 ^6 t5 ^/ I  W5 L# w& [6 M+ v3 AHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
! a8 s; e4 v7 {' `% X                     LPSTR pConnString,                 // 连接字串
! G! X1 \2 A& O0 \! n* G                     LPSTR pUserPassword ,              // 用户密码
3 r  N. ]& s; W: ]- L                     ConnectOptionEnum ConnectOption )  // 连接参数
& m" }; Z' |, ?{
6 G$ V  G: E" ~, m7 ]* X! c
5 O. E9 Y& B8 k  t' X4 {    HRESULT hr = S_OK;        // 默认返回值' \$ l. Z2 {1 X1 f3 X9 i6 g  r
    _ConnectionPtr ptrConn;   // 定义Connection对象
! ?, Y  `! {4 |: x5 |$ U  i* F$ \; u  V. P1 p; _9 i
    try) J3 C2 e8 a' Z
    {
) b/ S( O/ t4 D        // 创建一个连接实体
! t# D0 M' Q+ I) T. }! ]$ _$ E        hr = ptrConn.CreateInstance( __uuidof(Connection) );; F& @# \7 a. v' d) D
, U' |, R3 z4 }8 i
        // 设定连接等待的最大秒数,默认是15秒8 D4 }7 J8 i3 z6 a" d# P
        ptrConn->ConnectionTimeout = 20" t) ]! C' M/ b: @0 e4 v

! B" }  i& e4 ?5 E0 G2 H4 u        // 打开连接5 q# ^& ^3 d2 R( w" a; O
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
) e' @5 i2 u2 Q* f: ~- i  W        return hr;4 R, P& i! b+ v& Q+ Q0 ~& z6 }0 q' d
    }9 n6 R3 ?+ C% P, }- C# y0 S
    catch( _com_error & pComError )
6 t+ p; u% W8 s  i' n1 e    {
" w, p& T9 B; @- M        …… // 错误处理
+ q, c9 c! L9 J  T/ k2 I  G        return E_UNEXPECTED;& Q; W0 U, ^' p9 E# M, g
    }) k2 R$ s; z9 U8 S; ~$ I+ }
}* H8 p  ~- T6 ~
0 @: _: J8 K, P* O

4 T" N% d! X: p& R0 H4.执行一个SQL 查询,得到数据集(recordset)6 L% s, n4 u" t" Z$ |$ l1 k  ?
, k, F  k2 Y* w) |$ ]/ ^( M
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
. w# _+ J  t& {4 _7 ^8 A2 L" F{- P/ }; T' g3 ^
    try
1 q7 V: v( u3 r- R' M5 q$ N    {
" E+ a* K4 n: V" ]        RecordsetPtr ptrRS; // recordset 对象
: x7 N% y: W' y# D, Z, ?% S
$ j+ j# @1 Y1 ~( [; R( O4 e# {        // 创建recordset 对象实体
& B# @- ?; S- K9 G- V8 y" U) Q: N        ptrRS.CreateInstance( __uuidof(Recordset) );6 S2 o) q$ q0 d; z% ?
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
4 l* \3 r9 u% ]' ^: E4 t( r0 IadLockUnspecified, adCmdText );
) |9 I6 k! I9 w  }
  b" F' w! o" {( L2 i: K) n% q        或者0 ~$ H7 X8 o; h* z
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
$ F+ O) ~- G/ @/ l        return ptrRS;' T# [9 l1 J+ K" n
    }
4 Q) V( b, g4 t- `* T1 B: P0 m    catch( _com_error & a_pComError )
( x' ^& k; y6 f3 I! I) A' B" O    {
3 b2 q, Z4 k9 \" z3 D( @        ….// 错误处理
/ S8 F3 v8 J0 n7 P. |" F        return NULL;
1 @" i, P4 C3 x4 ~6 l& _1 `    }$ V- M4 c2 y: x" r$ {9 s- S, [2 K
}
5 P. d: j( u. @: c/ }7 C& _+ B) v& y! I( N# E8 G

) N2 e$ J8 `% ?+ i& a" s/ W$ q5.通过数据集(recordset)得到列的名称
2 e  l& G6 ^; `* W1 M1 H3 z2 l& l
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象
$ y% Y( f' h6 ~5 W; @3 f                        char strColNames[][255],
7 g7 |' X+ s8 ?7 ]4 I) Y2 t                        DataTypeEnum iColTypes[] )7 I4 Z, E, b! }  z* b
{  w" {. V& u8 i- }0 k" \, L
    try
5 p; J7 H4 y& k, v- ^5 z* `    { // 参数变量
( j) D2 d6 c: z2 m6 ]- Q+ T/ a        _variant_t l_vaIndex;4 E; e0 I( k. J. ~& f
! p: [* z4 c( K8 B0 A
        l_vaIndex.vt = VT_I2;$ ?' O% [, h( N- J) q
0 D% p, `+ [" k; g" f* a0 H' P4 c! f
        // COLUMNS总数
& n; ~' |9 z9 ]% Y7 Z( V- @        long lColCount;( L4 S& N# R. t: t! _5 J: O' n
0 K* B- ]& x0 P' S4 U, P
        lColCount = ptrRs ->Fields->Count;1 \5 Q5 r+ h$ g" \$ }& P0 `. Q
9 H: n6 k) ^+ s( i
        // 循环取得列的属性和名称
, e% u# N/ O2 S- e4 s& Y        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
6 _% t3 H* ]7 X3 b        {
1 s( g' d& j) W7 g+ O0 H* C& W) |            l_vaIndex.iVal = iIndex; // 设置循环索引( |& j6 }( }, D$ h, {
$ Z: S0 Y1 S) I4 {  `
            // 取得字段名称
: _& H2 K& v) [) z# N0 N            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
- ?# @  J# G+ [- F" ]$ \
) v3 |4 _9 S  B, ?4 I8 b4 J5 d            // 取得字段属性
. Q0 ?  d. b9 Q+ w1 X, f: y5 A" ^            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
$ O: Q5 Z1 l( h$ V( {        }
" U# C5 d2 A5 K+ j        return S_OK;1 L# I# y6 q6 E' g/ f
    }# y$ l$ `: J' o
    catch( _com_error & a_pComError )
: ]4 D" r4 |8 N% n( K9 `( Z1 W    {# @& F- X& [5 _% C$ ?9 ?! K. L$ x
        …. // 错误处理& p/ n/ l% Z& K
        return E_UNEXPECTED;
( M; I% F* Z  L/ g' J6 h+ t    }8 ~4 _2 {+ P. P
    catch(...)
' w3 J  }; M& g  L3 K" h    {0 k# P6 ^: N+ Y- _* f# n! j7 O2 `
        …. // 错误处理
6 E* x! ?) C4 `) B& a. G3 {        return E_UNEXPECTED;
0 A) P5 g; o. a    }
6 x; ~( {' t0 A3 T! R}
1 s% U" n" s* y* Z# _) Z7 `5 n( e/ y; }7 h# N$ G2 `
, f8 ^; f& K. {: U3 ^4 {
6.通过数据集(recordset)得到当前行记录. R4 C  O: b3 Q( H" Z
1 H& O; a' `  u& t. n$ |* O6 O
HRESULT getOneRecord( _RecordsetPtr ptrRs,8 N) R& `7 K+ O6 I4 c6 i
                      const long lNoOfColumns,( M: c# M: B9 G- h* e: {
                      _variant_t varValue[] )) X8 ~; P& P; Y- V' t, |
{
$ V  s$ r5 s  u3 T1 A0 A    try
* L3 w! _) ~- w7 s8 C    {, u( l' f, E. t1 h3 y0 _' a: J
        // 参数变量) R) u7 ^, z; E5 @: U; S  t* C" z3 ?
        _variant_t l_vaIndex;
6 U/ r. ~3 b8 J, I( C. ?8 @: ]* v        l_vaIndex.vt = VT_I2;
- l; }& h" s) c' L2 X8 h$ Z2 A8 w5 Y2 P* e' A3 M
        // 循环取得列的值
" Q& c% \+ F7 J* m  v6 j% _0 M        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )+ i4 \4 P- c% s
        { 1 q! Y: o/ m  P0 |: c
            l_vaIndex.iVal = lIndex;. a0 a* M% C! ~8 H4 X5 b2 @

2 h: M/ D4 V7 [  t6 l9 U            // 取得字段值
6 w. V; L4 ]! V, S! l5 P            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
$ u2 T0 {$ b% i  O        }
+ ^0 \' c' {( ]- ^' b; q' d: z8 i        return S_OK;, o$ q2 }( R5 I( _, {* b
    }
' {3 O) w. e% O, r    catch( _com_error & a_pComError )' k! D6 a1 J+ y. j3 n3 z: N. q9 ?
    {
6 g4 ?1 E$ x# f0 k: {! }        …. // 错误处理6 G+ O0 }4 r' C5 F; X# t
        return E_UNEXPECTED;
; y' ?7 p( e: J( p, D    }
; ?0 M' b3 T* N& ?0 F) H: i    catch(...)
9 n, W9 E% q$ Z& O. @# R8 O% P% V    {* L: n. r. [& G
        …. // 错误处理
$ h9 c  ^3 u' ?1 K* z        return E_UNEXPECTED;- v: q4 h" C6 z0 F& B9 Z0 Y: z
    }( G+ a) E7 u6 b6 s- N- _/ Q2 }
}
" R* ^* r' C( `2 }* _
, Y  F9 r, v* E3 B+ t) i# U; e7 _. s; Z" o! p
7.出错情况下错误信息的取得
9 [) U( i6 ^% b! ]
& `. w4 l4 o. [5 m( h4 t( Z! d7 r/ [void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );  q$ l6 s7 ^4 ^
{$ P. C. Z6 }; I  d. S/ @
    // COM 错误取得
; ^4 q( z) ?) k8 x- l) K# @7 Z    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
2 Y8 R5 ~0 U5 q1 w; `7 O    char lpComErrorStr512];+ l1 s5 l( X4 T8 ^2 O  {, r3 T2 |
5 E; d- i) ?# X; K
    sprintf( lpComErrorStr512,
) [8 x: q/ F$ Q' C' e4 L2 T6 A1 y             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s "," e9 j/ r2 c" z/ ~( M4 m2 n; O
             pComError.Error(),                  // 错误编号
% h0 K1 v0 l, e  o+ Z9 y             pComError.ErrorMessage(),           // 错误信息
; W6 V8 s/ f' n( k5 M" s             (LPCSTR) pComError.Source(),        // 错误源
1 [, M3 \# v6 N, \             (LPCSTR) pComError.Description() ); // 错误描述
: w3 C" P: W( ]# w9 S& B+ C
8 ?0 k" f+ k5 b" p+ h* V+ u0 B$ A    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息+ M- s& }7 M( j
    // ADO错误取得
, W! `7 b- R/ P
$ o& u7 ~3 U5 r    ErrorPtr pErr = NULL;9 O! B  {9 S, y! x
    if( (ptrConn ->Errors->Count) > 0), H: w# C1 q" Z; I( [
    {) F9 i4 N  @/ n  f( @% m
        long nCount = ptrConn ->Errors->Count;- P4 Z9 e  o4 M- P
        for( long i = 0; i < nCount; i++ ). R1 b+ H  U7 U/ j2 V
        {5 ]( V& b' Q; s
            pErr = a_pConnPtr->Errors->GetItem(i);2 J  p  P8 ]' u; M  \

+ ]- E% A, X; V            char l_pchErrorString[512];0 U/ d* M  p/ E% T' l
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",) X/ u) v4 D8 n5 q
                     pErr->Number,         // 错误编号2 V$ j4 I. f5 O! N' r1 f( T
                     pErr->Description );  // 错误描述% i/ C+ B" T) X- p9 k0 J3 W/ c3 e
        }5 X. {  u4 d0 Q4 i, s
    }5 p9 _- x1 J* P( u
4 \! b6 r( H* w
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
% R; c. b' Z/ v5 T2 p1 m- d    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-9-30 13:16 , Processed in 0.035405 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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