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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。. B$ [- Z' I' O/ S) f
. t4 x# k5 Q2 M) j" G
1、 用import导入ADO 的 COM 文件msado15.dll
3 [  q5 M* K. ?1 V) T) D0 J$ v5 E$ Q) L( d; g
例如:
' W7 O" a# H  I
8 y. {9 a$ H4 }7 p5 A. X) \  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\6 K1 Y. L/ |4 s( `
6 i: h5 J/ M7 K6 w# n
   no_namespace
( o2 j3 q$ ^" I/ D9 G- A1 w
9 [, ]9 \' ?9 G4 G  z' c! b1 ?# k) S: Q- q
2、COM 使用时初始化" Y  r( G  }, I3 ^" B3 b' P% I

# a2 \3 N2 ?1 H+ u9 d! n8 |' M4 jHRESULT ComInit()' Z- O( e4 E7 F
{
7 ~2 B+ m+ J8 a+ v    HRESULT hr = S_OK;             // 默认返回值
, ?1 R& i$ G  a' a3 R! _    if FAILED(CoInitialize(NULL))  // COM 初始化调用
  h' I0 V9 R1 H% K: y    {4 h. ~  Q$ s3 w
        CoUninitialize();
  r( Q' e; V) T! o        hr = E_UNEXPECTED;+ k1 A3 l  _/ e+ q5 T
    }" c4 r& Z( _5 R
    return hr;; S# T5 H" L5 v+ {* n$ X6 r, x
}, _$ Q) x& s! }; V9 h

* o- _. w7 e, a, D; ?7 n
& Y& R$ Y8 Q" U9 i* t3、建立数据库连接' O& l$ o+ W. m
" W/ n$ {7 ~7 Y' S- C& k: _
HRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名% J$ Z, v' m$ s& W# f# H9 N- o
                     LPSTR pConnString,                 // 连接字串
& z% o2 m* T3 Y) Z) f. ?' ^                     LPSTR pUserPassword ,              // 用户密码$ i5 Y7 F- K) m6 P3 j
                     ConnectOptionEnum ConnectOption )  // 连接参数) b' a, w+ `9 L. y0 n
{
9 K# b. F! `( y0 b' _7 F7 M. @4 {& `
    HRESULT hr = S_OK;        // 默认返回值8 O/ X- U$ U% t/ M4 }3 O5 E( [
    _ConnectionPtr ptrConn;   // 定义Connection对象( W+ Y% P4 h0 q6 B
0 c' d5 |, F6 D/ e# Y* |; V
    try
1 K# [/ u! x6 \/ l; D( f    {
; O- u( U- w& Y4 f1 Y8 ^        // 创建一个连接实体
4 q+ s+ c8 f' E        hr = ptrConn.CreateInstance( __uuidof(Connection) );/ ~4 }) i. f& o' s( [! g' Z  O
' m2 k  n& m/ T1 m7 g
        // 设定连接等待的最大秒数,默认是15秒- e& L. q: X; z! Q
        ptrConn->ConnectionTimeout = 20- A( l1 l+ }3 Z: X7 D, F/ n+ o, U

, J  |5 f) O4 u/ {, n        // 打开连接
& D4 L! c% t: N. R6 E8 ?, g2 ^        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
1 V" e- |# [6 M        return hr;
0 ^. h! W2 z! Y5 z8 ~7 y    }2 `8 ]1 u9 \) F1 W/ e$ j7 Z$ F
    catch( _com_error & pComError )
1 ^7 M% [, @% D, W/ K6 E    {( A6 g) _. t! w+ T8 ^2 C
        …… // 错误处理  J! m7 w* |- G# S* W/ R
        return E_UNEXPECTED;
+ @) X# Y$ B$ v' ^! v( A3 E    }
* g7 X8 S& s( W! v; p}
/ y$ U# o3 N4 Y- {: E6 ?! \- t' l9 V0 g( y

9 a# o+ k- r& l2 H9 Q4.执行一个SQL 查询,得到数据集(recordset)  c8 J. R- i# p: J* _6 A

; U& g. _; \* A& ~8 W_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
% Z: o* N) @* G  y2 m{
# ]( I% R7 v" o" i* a4 R    try
/ w# P, Z! v5 |6 h5 S4 I  @    {4 Q4 q# o: F/ F! O
        RecordsetPtr ptrRS; // recordset 对象  q9 S! {  }& K, R
& n6 n& P* z  U( x" r6 v, T
        // 创建recordset 对象实体
* p  [, w2 k0 `+ t" I; n& C        ptrRS.CreateInstance( __uuidof(Recordset) );' c, {1 i4 Q# J0 ]. z1 l
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly, 7 z3 {! s; c8 E0 q; H% Q
adLockUnspecified, adCmdText );
& D7 ]6 s7 S1 K% `! y7 x3 ]+ [. E# B! S' J0 x" ?5 J
        或者( R3 [# q1 n' H1 m7 ?
        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );
! \- n5 l! f* x7 u0 s        return ptrRS;7 B! J# C8 y6 ^. S+ S6 D
    }
4 ~; f$ s% x7 l/ H  w" G    catch( _com_error & a_pComError )$ a( M7 L# O+ c( x
    {
* D$ h6 L! L' ^: Q# z* l8 o        ….// 错误处理5 H, Z' V9 T& C, ~7 M  K4 R
        return NULL;
2 S, [' b- |* V    }. |( Z4 O7 b+ Z- c  U
}& O. H: y' R1 A6 n
8 q" |$ q. o. `5 `  C

; f( [! ?# r/ @) U1 h* V* j, }, ]5.通过数据集(recordset)得到列的名称
+ a+ p. w8 P6 o, `0 o4 Q5 {  @. ?" b; [! d
HRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象% u- i1 I( N# s8 ]
                        char strColNames[][255],
5 \& G$ x1 l# a. ^9 a, k1 M9 o                        DataTypeEnum iColTypes[] )% o" I6 x9 {0 S- j) ]. l- ~- b
{
7 _7 M4 P& \$ r" g! X) ?5 @    try
6 \: Y  Z' N  S* J* z/ _    { // 参数变量
; N% S- F3 f5 G; f4 y: J/ C/ S        _variant_t l_vaIndex;  J% N5 _9 r. G

& o& |* o8 I$ T9 z        l_vaIndex.vt = VT_I2;0 p( R: ^2 H- \
$ r$ ^3 J8 {0 d4 `& E8 N6 Q
        // COLUMNS总数
4 O! T  }7 h/ V& A' h. e        long lColCount;* x. E0 x4 K$ f/ h' L, ~

$ q+ `* D8 t' X# n# K        lColCount = ptrRs ->Fields->Count;0 V0 q: Y6 e6 |0 D, z) j" M
$ f" Y: T6 t) U$ e4 u! t! b) {$ h
        // 循环取得列的属性和名称4 r7 d- ]# f0 W; ^
        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )0 N! L3 u, F% A5 m# @2 e
        {# l. K+ n0 u  q
            l_vaIndex.iVal = iIndex; // 设置循环索引' I9 w6 ]! [! g* o

7 O7 R, m9 |' e8 ?9 C' ~            // 取得字段名称
% t8 a+ b+ X. p4 S+ g( b5 m$ g7 W& o            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);
. ?+ |0 \: J& I9 V$ ]3 w8 ^2 C5 x
            // 取得字段属性
8 x" `; F- N( Q            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;/ `" o: C+ K- @  q, n, Q
        }1 Z7 d0 @/ a9 G
        return S_OK;* n7 S  ]7 l4 h9 G! i
    }
+ S5 j' Q- g+ g7 T. z7 C    catch( _com_error & a_pComError )
9 {, v6 C$ ~: y: e0 x    {
' l- w9 n; P3 M/ E/ ?0 a. U        …. // 错误处理
8 P# M$ q% Q+ |# R& Z        return E_UNEXPECTED;6 w$ q/ b' A8 ]: \( {+ ?
    }
# t) E$ |; e) e8 m; `- |7 d& J    catch(...)" m+ p9 ]# r9 ~  v; B1 I
    {7 `) M, ?' `) ]8 Z
        …. // 错误处理( L- v. h" k1 O) E. G. S; r! J
        return E_UNEXPECTED;8 G. Z5 \% z- N0 c( ?' q
    }
# i* a5 ?$ U% a}% q' n, @* n. M+ z5 L3 K/ V. z7 y

) A/ }5 ?' v7 F6 {
( L5 ~# X, V  j8 V( |4 q6.通过数据集(recordset)得到当前行记录1 e& R3 R( ]& w4 C6 @9 D
$ ?1 \$ u! I5 e4 G8 A# W
HRESULT getOneRecord( _RecordsetPtr ptrRs,/ I8 ?" f% L* h) w' j
                      const long lNoOfColumns,
, L* B2 C4 _" ~4 X. N                      _variant_t varValue[] )
7 N- ^& S, |, k9 ]& A+ S, u{
1 A* U2 z+ y- |    try5 v! C7 W8 N% d: S  m
    {4 s/ u6 t) }6 ^1 r
        // 参数变量
4 h3 [8 {* m9 N        _variant_t l_vaIndex;) r* h7 K7 v7 c4 C- {: M( g
        l_vaIndex.vt = VT_I2;* R4 k* a( M, f7 m

0 F& R) Q% a0 H8 q& s0 R$ O/ U        // 循环取得列的值
' m6 s) ]* u4 V, x& s4 A' T/ {. ]        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )$ N( K2 i+ N5 r; H' l! F7 j$ F2 O! a
        {
) E( I/ T5 U0 Y+ q3 M, y. Y* d            l_vaIndex.iVal = lIndex;2 r" t8 m2 R7 n

3 _" {: D) Y, z7 X1 y& b3 ^$ C            // 取得字段值. m0 X- z# F, _
            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;+ T" Z1 U; H7 F* m% c$ b
        }
3 E! }/ `* I, y/ n& G9 `        return S_OK;
) L6 @: Q( S6 B( |5 ]5 o    }8 h: c# Z$ k9 w  e
    catch( _com_error & a_pComError )
, e- [# A4 C* J9 c$ ^5 I6 j! ^7 i( i( ~    {
$ `* P7 x7 m4 V5 q! F5 X        …. // 错误处理
5 E/ c+ ?; a: [0 `% e        return E_UNEXPECTED;+ ?: d' U4 \1 P
    }
  n  J# h( ~0 ^! I: m( ]6 X    catch(...)- c' K/ u8 ~( l$ C& S& _+ D3 y6 D
    {" U+ X' b0 t: P4 b+ s
        …. // 错误处理! r3 q' L3 b' ?+ Z7 y6 l4 w9 a
        return E_UNEXPECTED;$ {) F& o8 A. R. {# t
    }
7 L" c8 W& F4 g& d% P}
4 A5 @$ }. E/ ^5 B& T: \1 D: r. R9 _1 h6 V$ _. G9 U, L; p) I; Q8 M

0 y; z/ O, L+ W" W7.出错情况下错误信息的取得
' L, j5 b" W$ F: d' J, g, ~
1 S( R  ?- x7 L/ u: ^void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );
  r/ V$ a. M- X3 a{
  {/ p2 s) ^: V" d; F1 U    // COM 错误取得0 O+ S# b7 f' I& a2 A- `: P: R
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常
* ~9 j8 Q+ m& `: }! f2 \0 s    char lpComErrorStr512];
" f, \. ~& Q0 x5 s/ M+ b  K' @- e: Y9 n7 k6 o, I3 c
    sprintf( lpComErrorStr512,
# X% _! u+ ?0 D             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",3 B+ |0 E8 |/ z6 V- n! F& H
             pComError.Error(),                  // 错误编号
/ r# U* p' Z2 W$ [- F, g/ l             pComError.ErrorMessage(),           // 错误信息
) \% d+ N* t9 [$ q; ]9 |             (LPCSTR) pComError.Source(),        // 错误源
9 T9 S( h) }  v. M             (LPCSTR) pComError.Description() ); // 错误描述
% e' H3 A4 ?! ~" n$ X- X- b8 L* B; h0 g: p/ Z0 \* ^% z/ A
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
+ |9 a" ]! x, G" O/ B! u' `    // ADO错误取得
. p/ W3 ~) Z8 `5 g) O; R0 U. ~3 g2 ^% K# R$ K/ p& Z% L
    ErrorPtr pErr = NULL;# Z2 h% f0 ?/ L- [, }) @5 Z
    if( (ptrConn ->Errors->Count) > 0)
( W; v/ g6 b# A# J7 h; V/ |    {
, G5 _4 V7 i: O2 [1 I        long nCount = ptrConn ->Errors->Count;. `0 c7 @9 W- M$ `' i* S+ M+ z
        for( long i = 0; i < nCount; i++ )
% u! M7 `5 `' r0 D        {8 Z- ?) T) \$ p6 H3 L
            pErr = a_pConnPtr->Errors->GetItem(i);
0 U' A: h! D$ E% e
# T9 }. u3 z8 W. x4 E. o/ z' I7 u- f            char l_pchErrorString[512];  P) x6 H1 H3 Z* E) x( r6 O
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",- v- v2 {  j: [1 p; n* Z2 j
                     pErr->Number,         // 错误编号) \4 r% h7 C3 v6 q; I$ H* Y
                     pErr->Description );  // 错误描述
9 E6 R( H- |8 _        }
. p% m( _( r3 }$ W% m' _) O, {3 N    }3 [7 ?. W1 \0 D
+ Z0 M! e( [0 V: r" S% r2 Z
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问! t# B, l# K/ T
    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-8-14 00:59 , Processed in 0.018729 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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