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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。3 S0 ^6 a* j7 f+ `4 `5 V0 [5 O* ]5 ^
( R* h4 q6 z% @
1、 用import导入ADO 的 COM 文件msado15.dll5 M6 i, ~2 b5 H

# x) l" c) u% _( P例如:- R- q+ ~& y5 c  P6 l# J# H. t$ w
$ c* R! T6 ^# ]7 M) ^
  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
5 q0 b1 r( V7 N& T% ]; B
* Q8 B7 K2 H2 H' A+ _& s: m   no_namespace
% f, Z* x" @" }) d# s# V* i- b+ _! Y" G  f! \( P& N: d

: ~+ ?. q* m6 e2、COM 使用时初始化
" q) k( U* u9 e8 W6 g. N
+ r5 N7 a* k) }+ P. f! J0 w% T; jHRESULT ComInit()) x8 i+ J" q  Q: r2 @- v
{ ; S/ k+ b  k4 W- m* |
    HRESULT hr = S_OK;             // 默认返回值
: W+ {. Y  v8 W, ^. ?4 `5 b7 p9 G    if FAILED(CoInitialize(NULL))  // COM 初始化调用
* F6 ?" J8 q1 ~4 S5 ~% y9 Y    {
3 ?6 U& K( M/ l  N( F        CoUninitialize();
" W  @$ l2 M2 u+ D3 ^2 l0 l5 a        hr = E_UNEXPECTED;
6 \4 |, W# I( ?4 E5 n    }3 |+ ]! A6 A" _
    return hr;4 d6 }/ Z% Q0 Z( ~5 j
}4 l; b+ Q7 @  n& t0 L) E- Z4 ?

! F+ P) P1 G2 W+ H" _
3 [) @& f1 s2 L& i) b8 P/ i3、建立数据库连接
, h8 \' Y' l% `: l7 g0 ]9 o! W3 S7 r* J6 I
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名
$ d  T  K) v1 |; l. X2 D( g% O7 v. s# z                     LPSTR pConnString,                 // 连接字串 : s% ^; n: t! [% ^5 X+ Y, H1 g
                     LPSTR pUserPassword ,              // 用户密码1 X  G) r  Z8 @
                     ConnectOptionEnum ConnectOption )  // 连接参数6 r. i3 M2 X/ j( R. l
{
  W4 ]; u7 O9 u5 @' k; ^2 w: D* ]( r( A0 p9 {  b2 x
    HRESULT hr = S_OK;        // 默认返回值
/ A7 V0 p! Z9 p7 H( j5 U2 ?    _ConnectionPtr ptrConn;   // 定义Connection对象
5 y) f7 T6 ?& R6 D( O4 ?* }# Y( P4 F5 j2 @
    try7 |' Q% o9 h: B0 M
    {
9 L2 m* B6 f* C- q3 v4 d* S        // 创建一个连接实体
4 ], b5 [1 G  S3 Z- c! N        hr = ptrConn.CreateInstance( __uuidof(Connection) );, q* x( i& ^8 w: U8 \. Q
* S6 X' q: P# m9 ^2 _0 C
        // 设定连接等待的最大秒数,默认是15秒
+ m$ o9 B! F- `1 i! k        ptrConn->ConnectionTimeout = 20
$ w. i- W$ ]; H6 m0 I9 }- N+ u( Q% I. I( J, U* _& I$ Z
        // 打开连接8 j! a4 N2 L4 `) W2 a- J3 y3 u+ q# @4 P
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
8 D( d, m3 ~6 D1 J2 h        return hr;9 f8 F# r# i& n% o& q
    }# B) }& }8 J9 g7 \- q3 [- F+ ]7 N
    catch( _com_error & pComError )
+ {1 q7 m+ A# @! H    {
  k' M: \1 w" Z% Y: e        …… // 错误处理
8 i  O  y6 R" O! a: f1 ^  Z7 m$ d1 @        return E_UNEXPECTED;
: {5 O, O1 O& F2 b    }! w! S# i; N2 A
}
! I" w  E2 s8 |1 O6 p7 b5 m( ?; A" q) e, ]

& y/ n! K( F5 r( J; H+ ?/ x4.执行一个SQL 查询,得到数据集(recordset)  P' A# z& O! s8 j
: h$ X+ {! C% _
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )! J+ N* X% d2 N" b
{
; U9 v5 Q2 w; g( @$ A3 ]/ i    try2 A, ?: A# a9 f" d$ M
    {/ j0 Z# {- P4 G( B# F4 e
        RecordsetPtr ptrRS; // recordset 对象
" m- c3 h: d8 P5 l
$ w; E" {( D" G0 m  F% P8 m% i        // 创建recordset 对象实体: `1 U' v" ^# Z7 F( A
        ptrRS.CreateInstance( __uuidof(Recordset) );. v; q" f2 z5 w+ E0 y9 ~
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
8 o4 p6 m6 e0 x% ?7 badLockUnspecified, adCmdText );
. `6 u+ B( S, C3 f
3 [8 F: I4 E. z$ M$ t        或者) |( x  i+ y! ~: A( j
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
6 ]$ F- i9 s9 M4 {# y        return ptrRS;# O3 `8 I2 g& ]  u1 W# I
    }9 F1 K  h/ C- Y4 y& c9 `1 l* u
    catch( _com_error & a_pComError )
1 E: X  E0 n8 U/ k    {/ }; [9 e, i8 w2 W. |4 F+ X1 F
        ….// 错误处理7 T) l3 w& v( L- M! m) d/ W
        return NULL;
  P; q0 e$ I; |7 C. c9 g6 O, ?# e2 l    }9 [5 o% B0 p2 M1 c4 |+ o/ ?
}
4 R* B! @: }. t2 b  ~: L& b9 p& `
. l/ x# ~4 t1 [2 L# \
  T% Z: h" S0 g3 P8 c+ t) I, w5.通过数据集(recordset)得到列的名称
* h* x. T; W* _+ L! M( k7 z+ b* M( r* k! G/ i3 p
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象" N6 T" T7 S  m7 ^% H
                        char strColNames[][255],: p8 Q- v; @% X5 ^5 l
                        DataTypeEnum iColTypes[] ): V1 d( {- |0 i0 I6 X( L
{
4 B0 \- f8 m% m: ^& V3 C    try
% m& [1 `: J( i    { // 参数变量6 Y% }. x- ]5 O" N2 I$ N
        _variant_t l_vaIndex;
; @+ x: k6 @$ _# }1 g7 X. @
2 E8 W# L6 {! N" G- j$ b: |7 u$ T        l_vaIndex.vt = VT_I2;6 T- R! Y+ t" Y2 H9 X

* v5 L6 H7 E6 Q) k1 \7 o        // COLUMNS总数
7 Q2 y- `3 I& H6 m& D% @+ d7 \# `, w        long lColCount;
  @* X& l$ H5 R1 D5 V$ f) g& ~" L8 F! ~& j: i5 \) B4 M
        lColCount = ptrRs ->Fields->Count;# n$ u0 D4 ^# l! _4 W" }+ O% d* i3 Q3 N

# C# q1 x5 h$ [) ?9 _; }        // 循环取得列的属性和名称
' G; o& \/ u; i/ P& ~- C        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )+ v* z0 Q" H* z+ m# P
        {) s& M3 }( f6 C  f
            l_vaIndex.iVal = iIndex; // 设置循环索引: I* j+ q* r4 z' V  A( i/ t2 \* N

$ B4 G# a1 t% |/ k& a  a            // 取得字段名称
5 O9 p6 t3 d0 z3 _            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);/ ~& y7 v- {* y; o3 ?- |

( e" W$ _' m0 ]9 v3 H1 [            // 取得字段属性3 [% m. r  ^  l9 C4 f
            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;
) H% e; {, J: f7 _# ]4 i  W        }; z, r) b4 v0 v
        return S_OK;# Z1 U* F6 l; r
    }& V6 q  u& x- W) ], l2 L
    catch( _com_error & a_pComError )
! t6 G) S' L5 r  b- c" p    {
" A" A8 F7 V0 W3 C1 N' K        …. // 错误处理
& Q3 V) o' p7 t$ h( Y% w: M        return E_UNEXPECTED;
/ P/ I# s  H9 f% d    }7 G( f) l: H# F% O
    catch(...)
; `3 ^" o( ?5 T9 [4 U# ^3 n    {
' N- Q$ I2 r& A* n; o! n        …. // 错误处理4 }5 X9 U" t( V  ^& Y" L
        return E_UNEXPECTED;( T6 d5 k! F- s) Y; ^/ |. w
    }" U; S$ X0 A6 E4 }6 q: x- j2 p
}
. b1 L9 S, T3 V7 t0 h+ I$ q
% f7 c9 {4 \" W! [& ^& V) q% G& E
. t5 }! C* v) N( a+ x, E* [6.通过数据集(recordset)得到当前行记录$ x5 ?' k9 c( i8 K) E) O

4 `& v. i1 w9 I- KHRESULT getOneRecord( _RecordsetPtr ptrRs,
* ?6 ?) _9 [" y. [3 Y7 o6 R2 ?                      const long lNoOfColumns,5 n6 E% d0 B' v) V+ K
                      _variant_t varValue[] )
) S$ E( k/ r! s: p{( J& U0 D  V' ]( R2 z$ S2 P8 V& V
    try
6 ]; H* ]2 W# p& z% B$ ?    {
% b0 e6 y# c( b. E# P        // 参数变量- D/ z  @$ t: k; n4 Z
        _variant_t l_vaIndex;
' r/ p. \) e% l* x8 p) Q4 p        l_vaIndex.vt = VT_I2;
  o3 ?$ j7 J, h1 N% |2 w4 f7 ]! R9 [7 \8 E, H: T
        // 循环取得列的值5 V0 [# G% j: Q4 N% `
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )
3 y1 G1 u' q0 O1 Z        {
- j. f) F! I: }# y/ g/ i  d            l_vaIndex.iVal = lIndex;/ e& Q3 d8 W1 y7 y7 t5 |
/ ~8 P9 v! j: I5 r
            // 取得字段值
# n4 K% u# o' [6 p, o9 m2 s            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;0 K+ q( C+ Z( P, k
        }- p8 L8 Q) C1 K& z0 K7 H. C8 S
        return S_OK;
# ^) h0 V( h' \    }) `* u( {) V" x' X9 r' I9 p2 C5 S
    catch( _com_error & a_pComError )
5 B+ L5 C  ^/ o" J5 J    {
* [8 h1 T+ |) g) I        …. // 错误处理3 x2 z& {" a' O
        return E_UNEXPECTED;( D& s6 D4 X( c0 G8 S
    }: p7 n9 C) x9 l" g1 q
    catch(...)
' S8 A4 i2 f# N; T0 D/ U! I    {
* v/ C* ^) ]% Y6 F" h) \5 T* O        …. // 错误处理7 V  M: Y* r2 i- M% M. q! t) q
        return E_UNEXPECTED;: N( L) {0 c4 |5 ^% c/ V& b# s$ t
    }
0 {* u, {8 D/ Y% |}
- U" @/ B/ t7 g  ^. l/ b! A; N: H* K) Z# h! E0 n; G. a

2 [, {! V6 x" i7.出错情况下错误信息的取得
5 q7 K1 S0 R) @) G& ^4 T  x# l/ c& n: h! U5 c/ O9 P9 A
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );- p, Z3 Y1 ^$ f( Q) Z' f1 T" }
{
, b$ l, L: c0 y8 R/ u    // COM 错误取得: v: B- K9 p, Z" @7 d5 Y& z
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常$ @/ V* G+ [7 w! D* t! w* c
    char lpComErrorStr512];
5 Y( h1 r! V$ P+ f9 v% [- E+ g7 E2 _
    sprintf( lpComErrorStr512,
4 z" G. ~1 ~# C# U             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
! \9 L1 X: M3 C$ F" T% x' L9 F) b             pComError.Error(),                  // 错误编号
/ a9 _& o* p+ j3 u+ q- \* p             pComError.ErrorMessage(),           // 错误信息
) F3 y7 `" ^, u9 ^0 I# b             (LPCSTR) pComError.Source(),        // 错误源
& Q9 B4 i$ _, ]/ q/ w             (LPCSTR) pComError.Description() ); // 错误描述- @9 ]& Q$ H% T% O9 i: M

0 U" a) ?$ F6 q+ `5 a% Y3 Y    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
( B/ o. j. x1 [$ E0 z) w8 W+ {* S* {1 J+ j; U    // ADO错误取得& f0 u. |0 B' O: I
  e. r% H, D& C! T/ J' I; W8 ~. o: s
    ErrorPtr pErr = NULL;
" g. \9 i. Z  f3 e    if( (ptrConn ->Errors->Count) > 0)0 ~. E* S& i$ \+ q2 n
    {
5 n9 ^5 K* I) t% f, b; A/ c$ Y* t4 A        long nCount = ptrConn ->Errors->Count;
" s# [* g/ H5 p3 G        for( long i = 0; i < nCount; i++ ), G% O% ^, x& Z, a* C
        {$ R9 I6 _. P: E' N& z6 D' F5 N
            pErr = a_pConnPtr->Errors->GetItem(i);
2 l/ V  @# O6 e7 e  ^* p; |) z0 o- |; D0 p
            char l_pchErrorString[512];
" m' V6 y# n- d6 L/ w$ L            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",5 Z3 U  T$ V& Z: E. a: F
                     pErr->Number,         // 错误编号
6 S$ M' m9 p. Q3 [                     pErr->Description );  // 错误描述
1 Y! w: |# g9 r% R! S        }  ]- m, v( _8 H4 d
    }: i) y7 G4 S* K) [/ t
8 g" P& H% a0 `9 k; N/ w
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问
$ Q. ~8 i. ^. M) E5 w3 M    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 10:15 , Processed in 0.015400 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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