VC++下使用ADO操作數據庫


VC++下使用ADO操作數據庫主要要用到 _ConnectionPtr,_CommandPtr,_RecordsetPtr三個ADO對象指針,我查找了相關資料,發現網上源碼很多,但是都相對凌亂,於是自己也試着寫了一個簡單的例子,有什么問題,希望大佬們指正

關於三個ADO對象指針的介紹:

1,_ConnectionPtr接口返回一個記錄集或一個空指針。通常使用它來創建一個數據連接或執行一條不返回任何結果的SQL語句,如一個存儲過程。使用 _ConnectionPtr接口返回一個記錄集不是一個好的使用方法。對於要返回記錄的操作通常用_RecordserPtr來實現。而用,_ConnectionPtr操作時要想得到記錄條數得遍歷所有記錄,而用_RecordserPtr時不需要。

2,_CommandPtr接口返回一個記錄集。它提供了一種簡單的方法來執行返回記錄集的存儲過程和SQL語句。在使用_CommandPtr接口時,你可以利用全局 _ConnectionPtr接口,也可以在_CommandPtr接口里直接使用連接串。如果你只執行一次或幾次數據訪問操作,后者是比較好的選擇。但 如果你要頻繁訪問數據庫,並要返回很多記錄集,那么,你應該使用全局_ConnectionPtr接口創建一個數據連接,然后使用_CommandPtr 接口執行存儲過程和SQL語句。

3,_RecordsetPtr是一個記錄集對象。與以上兩種對象相比,它對記錄集提供了更多的控制功能,如 記錄鎖定,游標控制等。同_CommandPtr接口一樣,它不一定要使用一個已經創建的數據連接,可以用一個連接串代替連接指針賦給 _RecordsetPtr的connection成員變量,讓它自己創建數據連接。如果你要使用多個記錄集,最好的方法是同Command對象一樣使用 已經創建了數據連接的全局_ConnectionPtr接口,然后使用_RecordsetPtr執行存儲過程和SQL語句。

代碼:(如何有小伙伴也會使用到VC++操作ADO數據庫可以參考微軟官方文檔,我這邊也參考了上面的源碼:https://docs.microsoft.com/en-us/sql/ado/reference/ado-api/ado-code-examples-in-visual-c?view=sql-server-2017)

/*
VC++下使用ADO操作數據庫簡單實例
author:chenyuan
1,向User表插入一條數據
2,查詢User表並輸出結果集
*/
#include "stdafx.h"
//stdafx.h" 包含如下文件
//#include "targetver.h"
//#include <stdio.h>
//#include <tchar.h>
//#include <icrsint.h>
//#include <iostream>
//#include <iomanip>
//#include <string> 
using namespace std;
//(1)、引入ADO類
#import "c:\program files\common files\system\ado\msado15.dll" \
    no_namespace \
rename ("EOF", "adoEOF")

#define ConStr "Driver={sql server};server=127.0.0.1,1433;uid=sa;pwd=123456;database=YLTD2;"
//"Provider=SQLOLEDB;Server=127.0.0.1,1433;Database=PBMS;uid=sa;pwd=pp471006459;";
//"Provider=SQLOLEDB.1;Password=pp471006459;Persist Security Info=True;User ID=sa;"
//"Initial Catalog=PBMS;Data Source=127.0.0.1,1433";
//以上這三條strConnect語句都可以用
//要注意修改用戶名uid、密碼pwd、數據庫名database

#define GetValue(ptr,name) ((char*)(_bstr_t)(ptr->GetCollect(name)))

int ExcuteStr1(_bstr_t sql);
int ExcuteStr2(variant_t sql);
int main()
{
    ExcuteStr1("INSERT [dbo].[User]([Name],[DisplayName],[Password],[Status],[Sex],[Tel],[Mobile],[Email],[RoleID]) Values('C++Test','yuanker','123456',1,1,15911111111,1111111,111111,1)");

    ExcuteStr2("SELECT * FROM [dbo].[User]");
    system("pause");
    return 0;
}

int ExcuteStr1(_bstr_t sql) {
    //定義ADO對象指針。初始化定義上的指針。
    _RecordsetPtr m_pRecordset = NULL;
    _ConnectionPtr m_pConnection = NULL;
    _CommandPtr m_pCommand = NULL;
    HRESULT hr = S_OK;
    if (FAILED(CoInitialize(NULL)))//CoInitialize用來初始化當前線程COM庫,后面CoUninitialize與之對應,用來關閉當前線程的COM庫
        return -1;//如果初始化失敗則返回-1
                  //初始化連接參數
    try
    {
        if (SUCCEEDED(hr)) {
            _bstr_t strConnect = ConStr;
            //創建實例
            m_pConnection.CreateInstance(__uuidof(Connection));
            /*打開連接
            ConnectionString   可選,字符串,包含連接信息。參閱 ConnectionString 屬性可獲得有效設置的詳細信息。
            UserID   可選,字符串,包含建立連接時所使用用戶名。
            Password   可選,字符串,包含建立連接時所使用密碼。
            Options   可選,ConnectOptionEnum 值。決定該方法是在連接建立之后(異步)還是連接建立之前(同步)返回。adConnectUnspecified:(默認)同步打開連接。adAsyncConnect:異步打開連接。ConnectComplete 事件可以用於決定連接何時可用。
            */
            m_pConnection->Open(strConnect, "", "", adConnectUnspecified);
            m_pCommand.CreateInstance(__uuidof(Command));
            // 將庫連接賦於它
            m_pCommand->ActiveConnection = m_pConnection;
            // SQL語句
            m_pCommand->CommandText = sql;
            // 執行SQL語句,返回記錄集
            /*adCmdText: 表明CommandText是文本命令
            adCmdTable : 表明CommandText是一個表名
            adCmdProc : 表明CommandText是一個存儲過程
            adCmdUnknown : 未知*/
            m_pRecordset = m_pCommand->Execute(NULL, NULL, adCmdText);
            if (m_pRecordset)
                if (m_pRecordset->State == adStateOpen)
                    m_pRecordset->Close();
            if (m_pConnection)
                if (m_pConnection->State == adStateOpen)
                    m_pConnection->Close();
            CoUninitialize();
        }
    }
    catch (_com_error &e)
    {
        cout << e.Description() << endl;
        return -1;
    }
    return 1;
}

int ExcuteStr2(variant_t sql) {
    //定義ADO對象指針。初始化定義上的指針。
    _RecordsetPtr m_pRecordset = NULL;
    _ConnectionPtr m_pConnection = NULL;
    HRESULT hr = S_OK;
    if (FAILED(CoInitialize(NULL)))//CoInitialize用來初始化當前線程COM庫,后面CoUninitialize與之對應,用來關閉當前線程的COM庫
        return -1;//如果初始化失敗則返回-1
    //初始化連接參數
    try
    {
        if (SUCCEEDED(hr)) {
            _bstr_t strConnect = ConStr;
            m_pConnection.CreateInstance(__uuidof(Connection));
            /*打開連接
            ConnectionString   可選,字符串,包含連接信息。參閱 ConnectionString 屬性可獲得有效設置的詳細信息。
            UserID   可選,字符串,包含建立連接時所使用用戶名。
            Password   可選,字符串,包含建立連接時所使用密碼。
            Options   可選,ConnectOptionEnum 值。決定該方法是在連接建立之后(異步)還是連接建立之前(同步)返回。adConnectUnspecified:(默認)同步打開連接。adAsyncConnect:異步打開連接。ConnectComplete 事件可以用於決定連接何時可用。
            */
            m_pConnection->Open(strConnect, "", "", adConnectUnspecified);
            m_pRecordset.CreateInstance(__uuidof(Recordset));
            /*
            ①Source是數據查詢字符串
            ②ActiveConnection是已經建立好的連接(我們需要用Connection對象指針來構造一個_variant_t對象)
            ③CursorType光標類型,它可以是以下值之一, 請看這個枚舉結構:
            enum CursorTypeEnum
            {
            adOpenUnspecified = -1,///不作特別指定
            adOpenForwardOnly = 0,///前滾靜態光標。這種光標只能向前瀏覽記錄集,比如用MoveNext向前滾動,這

            種方式可以提高瀏覽速度。但諸如BookMark, RecordCount, AbsolutePosition, AbsolutePage都不能使用
            adOpenKeyset = 1,///采用這種光標的記錄集看不到其它用戶的新增、刪除操作,但對於更新原有記錄的

            操作對你是可見的。
            adOpenDynamic = 2,///動態光標。所有數據庫的操作都會立即在各用戶記錄集上反應出來。
            adOpenStatic = 3///靜態光標。它為你的記錄集產生一個靜態備份,但其它用戶的新增、刪除、更新操

            作對你的記錄集來說是不可見的。
            };
            ④LockType鎖定類型,它可以是以下值之一,請看如下枚舉結構:
            enum LockTypeEnum
            {
            adLockUnspecified = -1,///未指定
            adLockReadOnly = 1,///只讀記錄集
            adLockPessimistic = 2, 悲觀鎖定方式。數據在更新時鎖定其它所有動作,這是最安全的鎖定機制
            adLockOptimistic = 3, 樂觀鎖定方式。只有在你調用Update方法時才鎖定記錄。在此之前仍然可以做數
            據的更新、插入、刪除等動作
            adLockBatchOptimistic = 4,樂觀分批更新。編輯時記錄不會鎖定,更改、插入及刪除是在批處理模式下完成。
            };
            5.option可以取以下值
            adCmdText : 表明CommandText是文本命令
            adCmdTable : 表明CommandText是一個表名
            adCmdProc : 表明CommandText是一個存儲過程
            adCmdUnknown : 未知
            */
            m_pRecordset->Open(sql, (IDispatch *)m_pConnection, adOpenDynamic, adLockOptimistic, adCmdText);
            m_pRecordset->MoveFirst();
            while (!m_pRecordset->adoEOF)//此處adoEOF為上面的 rename("EOF","adoEOF")
            {
                /*string Name = (char*)(_bstr_t)(m_pRecordset->Fields->GetItem(_variant_t("Name"))->Value);
                string Password = (char*)(_bstr_t)(m_pRecordset->Fields->GetItem(_variant_t("Password"))->Value);*/
                string ID = GetValue(m_pRecordset, "ID");
                string Name = GetValue(m_pRecordset,"Name");
                string Password = GetValue(m_pRecordset, "Password");
                string Sex = GetValue(m_pRecordset, "Sex");
                cout << "編號:" << ID << "  姓名:" << Name << "  密碼:" << Password << "  性別:" << Sex << endl;
                m_pRecordset->MoveNext();
            }
            //關閉結果集
            if (m_pRecordset)
                if (m_pRecordset->State == adStateOpen)
                    m_pRecordset->Close();
            if (m_pConnection)
                if (m_pConnection->State == adStateOpen)
                    m_pConnection->Close();
            CoUninitialize();
        }
    }
    catch (_com_error &e)
    {
        cout << e.Description() << endl;
        return -1;
    }
    return 1;
}

附:

附錄來源:http://blog.csdn.net/umbrella1984/archive/2005/05/29/383628.aspx

1、_variant_t

(1)、一般傳給這3個指針的值都不是MFC直接支持的數據類型,而要用_variant_t轉換一下
_variant_t(XX)可以把大多數類型的變量轉換成適合的類型傳入:
(2)、_variant_t var;_variant_t -> long: (long)var;
_variant_t -> CString: CString strValue = (LPCSTR)_bstr_t(var);
CString -> _variant_t: _variant_t(strSql);
2、BSTR寬字符串與CString相互轉換

BSTR bstr;
CString strSql;
CString -> BSTR: bstr = strSql.AllocSysString();
BSTR -> CString: strSql = (LPCSTR)bstr;
3、_bstr_t與CString相互轉換

_bstr_t bstr;
CString strSql;
CString -> _bstr_t: bstr = (_bstr_t)strSql;
_bstr_t -> CString: strSql = (LPCSTR)bstr;
4、關於時間

Access:表示時間的字符串#2004-4-5#
Sql:表示時間的字符串”2004-4-5”
DateField(時間字段) select * from my_table where DateField > #2004-4-10#


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM