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

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

[复制链接]
发表于 2004-1-31 18:14:29 | 显示全部楼层 |阅读模式
  对于在WINDOWS上编写数据库程序的程序员来说,ActiveX Data Objects (ADO) 是最常使用的技术了,通过ADO可以简单的实现数据库的连接以及数据访问。但是在VC++中使用ADO时,却因为是使用COM的方式来调用,常常出现一些系统无法编译通过,或使用中程序非法出错的问题,在这里想大概介绍一下VC++中调用ADO的常用方法。
6 F0 R7 H- h7 y1 i0 V8 x' I4 Q2 y2 Z6 s& J& W- t# H/ z
1、 用import导入ADO 的 COM 文件msado15.dll
6 p  y' ?: v2 c1 V) y# w
9 d& F- H% Z" G8 x' C) H0 T例如:
5 p7 N& z, Z6 l( a; M" g! b$ Z# {
/ t8 N' L9 ^, v7 F+ W' K' I2 [  #import "C:\Program Files\Common Files\System\ADO\msado15.dll"\
/ `4 e: h4 T2 F$ \/ k% s& _+ i
   no_namespace
8 m/ F0 U+ b1 Y! k8 [' Q/ j& ~( {
  b8 j! e0 R+ m0 Q" l0 d# K0 H% ~) j
2、COM 使用时初始化
8 h! f% W* x2 E+ `" D1 b2 K$ d! c" Q/ Y# U* @* N
HRESULT ComInit()
# H) Z$ u* B% _, I& y% b& y  e{ - u! W7 o  _1 Y, @* `: D
    HRESULT hr = S_OK;             // 默认返回值9 L1 F9 l3 y2 ~1 }0 m
    if FAILED(CoInitialize(NULL))  // COM 初始化调用
" w5 G2 E7 w  |$ H5 \    {3 Q+ z% w0 V0 _; y
        CoUninitialize();
/ k4 Z* K2 d/ e, U8 [) p        hr = E_UNEXPECTED;$ [5 j9 T, ]8 s2 i6 x8 \( \
    }2 ]. ?; ^7 x3 i+ i
    return hr;8 A2 X" d7 {/ D% W# t% C
}2 x; G+ V1 \# f0 z* K& T5 L. [( j8 H* M

2 x, q3 E) g8 `: y1 ]/ L6 h* E6 ^( }% M' @2 L5 ^$ A" M6 }  Z4 w
3、建立数据库连接' i6 Q% F+ ~8 F2 y. Z* Y

) e& T2 h* e/ C& v6 }8 bHRESULT ConnectToDB( LPSTR pUserId ,                    // 用户名: O6 @) j; G$ D$ R9 U3 W
                     LPSTR pConnString,                 // 连接字串
. J& z% N5 p  b- y8 R                     LPSTR pUserPassword ,              // 用户密码
1 X# `: c7 k, ^8 E# ^  M                     ConnectOptionEnum ConnectOption )  // 连接参数
5 n& ~7 p+ J  X* g, E$ E3 j7 x{
1 J6 B7 f( a: e8 U3 U& R: e+ t
: ?& V& ^) s; r+ Y3 X7 Q    HRESULT hr = S_OK;        // 默认返回值7 t& x$ F& E5 ?5 Z
    _ConnectionPtr ptrConn;   // 定义Connection对象( `% Q# L9 q. {2 Y
# O. Z/ w4 h. q, X1 K
    try
" A8 ?' W9 g2 h: o: Y8 y    {: m; r/ E3 b/ J7 h0 T+ ?' b/ Y
        // 创建一个连接实体
: y' ~7 ^! j/ F0 E. S$ g        hr = ptrConn.CreateInstance( __uuidof(Connection) );
/ w  X4 M" b& E) O: t& A7 q; ]
; F8 P% R3 V4 E; v  ^        // 设定连接等待的最大秒数,默认是15秒
. Z6 Y$ D& ?- f* m" |2 f. p        ptrConn->ConnectionTimeout = 20; x' b: i% |( \, y
# j" j: @5 y' M5 _
        // 打开连接5 R. O" R+ ]( W' n  e$ o; X
        hr = ptrConn->Open( pConnString, pUserId, pUserPassword, ConnectOption );
/ R# r9 F- U% ]7 |6 M8 N2 u        return hr;4 ^6 Z# C' C2 H) R4 I
    }9 `- D, ^2 ^+ o+ R6 J
    catch( _com_error & pComError )
: q+ b, d7 X3 i8 x1 g! E1 ]# P9 P    {% b1 f) U- R& b0 Y2 w
        …… // 错误处理
! z% ~- M- f3 P5 {3 b5 W        return E_UNEXPECTED;0 H4 Q* s0 M, Z) A- j: J
    }6 }# R4 P9 j9 e) Q$ ?
}
3 T# D; X# d( [( D0 t3 ~7 q& P- y, _$ C

3 E7 Q: Q  K  ^# J5 O2 i$ x4.执行一个SQL 查询,得到数据集(recordset)4 m+ n; q/ v3 Q) Y- {
. z0 S  v7 k8 d1 t4 A+ K
_RecordsetPtr GetRecordSet( LPSTR strSql, _ConnectionPtr ptrConn )
; k: V; N2 u1 M{, y( F& V: Z( V/ n1 ~+ W
    try
' y. O) @2 ^2 N# W4 b; H- C+ P    {
! B/ c& h# D- M; {        RecordsetPtr ptrRS; // recordset 对象$ A6 d5 E; J9 x2 q* Q! n2 y" A
$ c4 C3 {& B6 C
        // 创建recordset 对象实体. U# o9 p9 T, v+ |' Y+ }/ ]+ s; J
        ptrRS.CreateInstance( __uuidof(Recordset) );- g8 p) |0 I# J+ y# }4 D5 o3 U
        ptrRS->Open( strSql, ptrConn.GetInterfacePtr(), adOpenForwardOnly,
2 V- z2 s3 W, W6 m- m: f% V6 cadLockUnspecified, adCmdText );
" S- o$ W# Z* Q1 F9 G; _: N
# Y! R+ Y* E2 V, k( e3 Y( D& z        或者
5 b6 M) w% _; |6 N: Y3 t        ptrRS = ptrConn ->Execute( m_ strSql,NULL, adCmdText );+ I, E2 l/ O" p
        return ptrRS;
2 W  e2 p! i6 j2 |    }
2 L' M. F% t: b4 \* A    catch( _com_error & a_pComError )" ?$ C& ^% Q/ M5 w2 o6 ]. I+ j
    {( p8 T0 e, N4 i4 i5 k
        ….// 错误处理; D" F" s5 [. S) ~' v* k
        return NULL;
1 R" |% z, C: p    }
- f4 _* a- _" I. a}
" i+ K" h0 G1 k3 f( f7 b8 w; E' X, U
, Y  Y+ z1 N8 {" R) E; t
5.通过数据集(recordset)得到列的名称
* l# m& Q1 S7 ~
; K  \, p. Z5 r, U8 ?" I- }( EHRESULT GetColumnNames( _RecordsetPtr ptrRs,        // recordset 对象; g3 {& H, t: w) |$ V
                        char strColNames[][255],1 C/ \1 r3 l* W/ R
                        DataTypeEnum iColTypes[] )
% f# O2 m8 w; y0 ?( X{( x) d, \3 H4 q
    try
! F4 l) N+ i! V/ q; }    { // 参数变量# V5 ]+ b7 ^0 r
        _variant_t l_vaIndex;
- d2 ]! c% A8 K* W, C4 `
5 K$ E2 Z% G/ L: R3 ~6 P% Z+ Z        l_vaIndex.vt = VT_I2;
4 H. b0 }) n+ r6 H+ ?* ^" D: C$ F, ]: F3 ^8 m% K  u4 u/ j5 v
        // COLUMNS总数3 R* q' Q* g7 B- V7 H
        long lColCount;. L; g, J, |" ^) o/ ?' ~3 q

- n6 G$ V1 P' w) j! t! u9 `3 b/ T        lColCount = ptrRs ->Fields->Count;3 `, g9 ^( z9 L, q; G- d6 P' l

  e0 Q5 M  ^) Z" l0 E5 p- I        // 循环取得列的属性和名称
0 F+ E+ B# d8 c# t7 b0 J. ~" Q3 H        for( int iIndex = 0 ; iIndex < lColCount; iIndex++ )
0 E+ _# w& `4 E  j; Q        {3 F/ J1 _( y  a: D) ^
            l_vaIndex.iVal = iIndex; // 设置循环索引
5 g- @) M4 Y; C3 a3 K: R$ l' u8 {( F% Z
            // 取得字段名称& f: X& D. k2 f7 ?1 D! ~( y6 U
            sprintf(strColNames[iIndex], "%s", (LPSTR)ptrRs ->Fields->GetItem(l_vaIndex)->Name);% o+ ]9 p/ U. i
7 a$ i1 f0 e2 m3 s+ m0 y- r
            // 取得字段属性
+ S9 g# V7 C& O. p( }7 `0 U7 D# \+ H( f            iColTypes = ptrRs ->Fields->GetItem(l_vaIndex)->Type;+ f' Q- [% ?8 l3 s% x4 w/ {8 p
        }) L8 Z# {. K& T) w# ]7 J
        return S_OK;
" F2 q: p' \7 v+ R. E8 C) ^    }
* J; N  ~: e4 ^# |; W    catch( _com_error & a_pComError )
/ n! f! T' X$ m+ Q% X0 Z    {, H3 m& h3 y$ {8 s3 r" j# F
        …. // 错误处理
2 s+ b% p4 F/ L8 i# _        return E_UNEXPECTED;
7 z5 C$ G# k7 C0 r; {0 v: _    }
& D3 R/ Y7 b9 D( Z: |8 A. [    catch(...)
8 f7 x3 f; C9 X$ z5 _    {
! m- C. ?* x5 y- G        …. // 错误处理
+ @: }. P/ a8 K4 u5 H; X        return E_UNEXPECTED;4 H7 \' {, J( ^5 N: d7 U
    }
! F4 T! o3 g0 b3 [4 g: c}
3 b5 g3 @& o% [0 s: U1 w9 R" n% k) ]4 {

1 s1 z6 W5 ]( [: y, A6.通过数据集(recordset)得到当前行记录+ Q" ~2 j  l, W: H8 G: P
2 N/ W, k6 I. }# x
HRESULT getOneRecord( _RecordsetPtr ptrRs,
" y9 l# O; R" T; L                      const long lNoOfColumns,
6 n1 q& I" y5 S0 i                      _variant_t varValue[] )) Y$ d6 M$ C$ X$ j1 C% n/ N$ ~
{
  o/ K, J2 U. m" _9 H# n    try
) x7 z0 V. o0 ?" c$ U/ n    {: [; u. }$ ~; \; x8 {' R" u) Q. B
        // 参数变量
& y1 q7 `+ ]  n1 i        _variant_t l_vaIndex;
% c4 v/ E' d9 v; }* H4 }6 W0 R* `$ {        l_vaIndex.vt = VT_I2;# D' J' c) L- p8 [& h: l( m

" x0 h4 B: G2 L( n* u! e, D        // 循环取得列的值/ {6 p3 g, c8 p( H/ K  _8 R+ V
        for( long lIndex = 0; lIndex < lNoOfColumns; lIndex++ )7 x4 j+ d. j' s- K. j) g1 A' Y
        {
/ F% n0 z! \. r0 J" `8 |            l_vaIndex.iVal = lIndex;1 n9 ?! [7 Z# g3 J1 g4 X
8 s. B4 g' o" f* b9 `' P
            // 取得字段值
6 O( s  A8 ?+ v. A# A1 Z            varValue[lIndex] = ptrRs->Fields->GetItem(l_vaIndex)->Value;
  Y  X" J* }: k1 Q        }
$ F+ M; Q. i' |, X4 b        return S_OK;
8 S6 F" U. n- S. W    }8 t/ p5 [: ]2 B5 O
    catch( _com_error & a_pComError )7 [3 o9 P' {1 L/ w
    {$ t: ]( z3 f# I( S7 {3 F! Y9 k
        …. // 错误处理1 h3 Q9 U5 L6 ~8 U. l' L" j- @
        return E_UNEXPECTED;
5 |9 Q& \1 A6 m! L( T0 b9 s    }" H- a; k9 Z1 i1 w* V7 W
    catch(...)" B! b) [- o" ^# h+ R9 x3 P! J
    {& j# I; ]3 P' o( r) ^, m
        …. // 错误处理3 `4 S: m4 R, N6 [/ `8 [' S
        return E_UNEXPECTED;1 B  b* J# j# m5 z$ b
    }
% y& q+ E8 w- R}
3 U2 T( X0 Z& L5 D' M4 a, f6 Y5 Y% R* y

  g. B1 l' C! K" Y' e  g* x7.出错情况下错误信息的取得' R! b6 E! G$ k6 a8 t
5 d0 S. L; u% ^1 e; M! q3 j
void ErrorFunc( _com_error &pComError, _ConnectionPtr ptrConn );) K" Y! k5 _9 y7 ]1 L
{
6 Y8 q1 S; R* @1 v8 K# n, l! ]! G0 X    // COM 错误取得  T6 a% V0 b  B6 o( ]  O/ d8 P  I
    // 当执行COM功能的时候,如果出错,可以捕捉到_com_error的异常# f/ g7 P" P7 B1 G) v1 d% u3 h: R* X
    char lpComErrorStr512];, @: m8 p& I# _8 x0 G, v

. S2 g, M4 i: b# E, G9 Y    sprintf( lpComErrorStr512,$ \9 ]1 x2 C' F: O
             "ErrorCode = %08lx \ Error Message = %s \ Source = %s \ Description = %s ",
' y% Z/ M( o3 z8 ^- |. }! ^4 _             pComError.Error(),                  // 错误编号
' S: Y2 r, ^; X             pComError.ErrorMessage(),           // 错误信息7 Q( D& a* {2 J8 H8 k+ p4 r
             (LPCSTR) pComError.Source(),        // 错误源
& _; ?& z8 O, j; q             (LPCSTR) pComError.Description() ); // 错误描述& @1 K$ ]% H% @( f
0 Y3 Y; a0 s' O5 M8 r+ R
    // 通过上面的代码我们可以看出,_com_error对象中可以得到COM所有出错的信息
; I9 I) Q. Z. m: Z    // ADO错误取得! a: Q1 i+ g1 V( {4 w

# d5 q4 T5 Q8 X$ t# c4 B# X; M! n    ErrorPtr pErr = NULL;
) `( \; ]* B7 X    if( (ptrConn ->Errors->Count) > 0)
) V% G" p* X/ n! F) A! v    {
2 k9 a( w2 P, a* S        long nCount = ptrConn ->Errors->Count;
% \  I9 r. B4 ^' V4 Z7 N$ k# H        for( long i = 0; i < nCount; i++ )) l- K% q7 d6 l; I2 q  [1 f
        {0 t; t* E% ~& z0 H# p  m2 P
            pErr = a_pConnPtr->Errors->GetItem(i);! n5 _. |% [. w7 G* m9 _+ b
; u) }& q9 y& l* n+ @6 F  F! u
            char l_pchErrorString[512];9 O6 m5 n) f8 ~2 |( a
            sprintf( l_pchErrorString,"Error:\n Error number: %x\t%s",
/ W0 H/ v) T. _- b# i- v                     pErr->Number,         // 错误编号
  J; w- x4 W7 t1 K1 V                     pErr->Description );  // 错误描述! h+ ^7 r+ x' W9 ^- F3 _. \
        }
' h7 j6 `+ c+ V6 e. k, e    }$ ]% A* ~& I- j# z
. Q8 ~# r( q5 Q5 a" S- S
    // ADO 处理出错的情况下, 在connection对象里面都有记录,可以通过访问$ Z& e0 B0 @  u: z
    // connection 对象取得错误编号和错误信息。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2025-6-19 09:03 , Processed in 0.015140 second(s), 15 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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