VC++ ADO操作總結
1、匯入庫檔案
#import "C:\Program Files\commonfiles\system\ado\msado15.dll" no_namespace rename("EOF","EndOfFile")rename("BOF","FirstOfFile")
使用ADO前必須在工程的stdafx.h檔案最後用直接引入符號#import引入ADO庫檔案,以使編譯器能正確編譯。程式碼如下:
ADO類的定義是作為一種資源儲存在ADO DLL(msado15.dll)中,在其內部稱為型別庫。
型別庫描述了自治介面,以及C++使用的COM vtable介面。
當使用#import指令時,在執行時Visual C++需要從ADO DLL中讀取這個型別庫,
並以此建立一組C++標頭檔案。這些標頭檔案具有.tli 和.tlh副檔名,#import引入ADO庫檔案的程式碼編譯後,在專案的目錄下生成了這兩個檔案。在C++程式程式碼中呼叫的ADO類要在這些檔案中定義。
no_namespace指示ADO物件不使用名稱空間,在有些應用程式中,
由於應用程式中的物件與ADO中的物件之間可能會出現命名衝突,所以有必要使用名稱空間。
如果要使用名稱空間,則可把第三行程式修改為: rename_namespace("AdoNS")。
rename("EOF","EndOfFile")表示將ADO中的EOF(檔案結束)更名為adoEOF,因為檔案的結尾也是以EOF結尾的,是為了避免與定義了自己的EOF的其他庫衝突。 至於改為什麼名字,可以根據自己的命名習慣自己確定。
2、初始化COM環境
OLE DB 是基於COM技術編寫的,ADO是OLE DB基礎之上的使用者程式,
OLE DB是一個COM元件,在訪問COM元件的時候需要初始化COM庫,方法如下:
(1) ::CoInitialize(NULL); //初始化OLE/COM庫環境
釋放程式碼:
::CoUninitialize();//既然初始化了環境,當然一定要記得釋放他了
(2)也可以呼叫MFC全域性函式
AfxOleInit();
3、三大指標物件的定義和建立例項
(1)
_ConnectionPtrpConnection("ADODB.Connection"); _RecordsetPtrpRecordset("ADODB.Recordset"); _CommandPtrpCommand("ADODN.Command");
(2)
_ConnectionPtr pConnection;
_RecordsetPtr pRecordset;
_CommandPtr pCommand;
pConnection.CreateInstance(__uuidof(Connection));
pRecordset.CreateInstance(__uuidof(Recordset));
pCommand.CreateInstance(__uuidof(Command));
要產生一個智慧指標物件,其實在定義的同時也可以初始化,如:
_ConnectionPtrpConnection(__uuidof(Connection));
_ConnectionPtr 是智慧指標
__uuidof() 用來獲取Connection全域性唯一識別符號
(3)
_ConnectionPtr pConnection;
_RecordsetPtr pRecordset;
_CommandPtr pCommand;
pConnection.CreateInstance("ADODB.Connection");
pRecordset.CreateInstance("ADODB.Recordset");
pCommand.CreateInstance("ADODB.Command");
4、開啟一個連線
pConnection->ConnectionString = "這裡的字串有下面四種寫法";//對連線字串賦值
pConnection->Open(ConnectionString,"","",adModeUnknown);//連線資料庫
//第二三個引數分別為使用者的ID與密碼,
因為在連線字串ConnectionCstring中已經設定好了,這裡可以為空。
第四個引數可以取下面兩個引數:
adAsyncConnect
非同步開啟資料庫,在ASP中直接用16
adConnectUnspecified
同步開啟資料庫,在ASP中直接用-1
ConnectionString根據不同的資料來源,分別對應不同的寫法
(要記下來很困難,可以在VB中利用ADO控制元件先連線好,再將其拷貝在VC中,這樣不容易出錯)
1)
訪問Access 2000
"Provider=Microsoft.Jet.OLEDB.4.0;DataSource=databaseName;UserID=userName;Password=userPassWord"
2)
訪問ODBC資料
"Provider=MADASQL;DSN=dsnName;UID=userName;PWD=userPassword;"
3)
訪問Oracle資料庫
“Provider=MSDAORA;DataSourse=serverName;User ID=userName;Password=userPassword;"
4)
訪問MS SQL資料庫
"Provider=SQLOLEDB,DataSource=serverName;Initial Catalog=databaseName;UserID=userName;Password=userPassword;"
5、執行SQL命令,得到資料
方法1:
pRecordset =pConnection->Execute("Select * from authors",NULL,adCmdText);
方法2:
pRecordset ->Open("Select * fromauthors",_
variant_t((Idispacth*) pConnection), //設定活動連線
adOpenDynamtic,
//遊標型別
adLockOptimistic,
//鎖的型別
adCmdText);
方法3:
pCommand->put_ActiveConnection(_variant_t((Idispatch*) pConn);
pCommand->CommandText = "Select *from authors";
pRecordset =pCmd->Execute(NULL,NULL,adCmdText);
得到資料之後,做一個迴圈取得資料:
While (!pRecordset ->adoEOF)
{
Str =pRecordset->GetCollect("au_lname"));
pRst->MoveNext();
}
SQL命令比較多,但是不去考慮細節,這裡只說出通用的方法
CString strSQL;//定義SQL命令串,用來儲存SQL語句
strSQL.Format("SQL statement");
然後在每個要用到SQL命令串的方法中,使用strSQL.AllocSysString()的方法進行型別轉換
6、com的專用資料型別
variant ,bstr ,SafeArray
variant變數的範圍包括很多,它是一種變體型別,主要用於支援自動化的語言訪問,
從而在VB中非常方便地使用,但是VC中比較複雜,它使用_variant_t 進行管理
bstr是一種字串變數,使用_bstr_t進行管理,這個類過載了char *操作符
7、關閉連線
if(pConnection->State); //不能多次關閉,否則會出現錯誤
{
pConnection->Close(); //先判斷狀態,然後再關閉,其它類似
}
pRecordset->Close();
pCommand.Release();
pConnection.Release();
//釋放引用計數
pRecordset.Release();
注意:呼叫Close()時用"->",呼叫Release()時要用".",為什麼?
因為智慧指標,_ConnectionPtr是一個過載了->運算子的類
_ConnectionPtr:它是一個介面指標模板。'.'是模板_com_ptr的函式。->是'介面函式'呼叫。
//forexample:
_ConnectionPtr m_Conn;
m_Conn.CreateInstance(....);//Createinterfaceinstance.
m_Conn->Open(...);//Openaconnectiontodatabase.
'->'是_com_ptr過載了的運算子.目的就是為了讓你呼叫模板引數的函式.
8、結構化異常處理
ADO封裝了COM介面,所以需要進行錯誤處理
如下例:
HRESULT hr;
try{
hr =m_pConnection.CreateInstance("ADODB.Connection");///建立Connection物件
if(SUCCEEDED(hr))
{
hr =m_pConnection->Open("Provider=Microsoft.Jet.OLEDB.4.0;DataSource=test.mdb","","",adModeUnknown);///連線資料庫
///上面一句中連線字串中的Provider是針對ACCESS2000環境的,對於ACCESS97,需要改為:Provider=Microsoft.Jet.OLEDB.3.51;
}
}catch(_com_error e)///捕捉異常
{
CString errormessage;
errormessage.Format("連線資料庫失敗!\r\n錯誤資訊:%s",e.ErrorMessage());
AfxMessageBox(errormessage);///顯示錯誤資訊
}
在ACCESS中使用日期比較
關於access中資料型別不匹配的問題between #1993-04-26# and #1993-05-26#
2006-10-11 16:06
/問題: |
獲取執行SQL函式後的返回值 EG:SUM(RoundInfo.RoundLen) from RoundInfo,Main where Main.Date between 2009-1-2 and 2012-2-3"
temp_Str=L“SUM(RoundInfo.RoundLen) from RoundInfo,Main where Main.Date between 2009-1-2 and 2012-2-3"
HRESULT hr = m_ptrRecordset->Open(_bstr_t(temp_Str), _variant_t((IDispatch*)m_ptrConnection, TRUE),
adOpenStatic, adLockBatchOptimistic, adCmdUnknown);
if(!m_ptrRecordset->adoEOF) //必需首先判斷資料集是否是空,否則如果直接GetCollect()的話,會報出錯誤
{
_variant_t varNo = (_variant_t)m_ptrRecordset->GetCollect ((long)0);
if(varNo.vt!=VT_NULL) //判斷是否是空記錄
{
AvgLen = (long)varNo;
}
}
函式總結:
m_ptrRecordset->get_RecordCount(&this->m_threeRoundEnough);
獲取查詢結果的數量(即個數)
_variant_t varNo = (_variant_t)m_ptrRecordset->GetCollect ((long)0);
這句話的意思是獲取第一列當前行的值,如果是查詢之後直接用這句話,則指取第一行第一列的值,取下一列,則加上
m_ptrRecordset->MoveNext();
如
hr = m_ptrRecordset->Open(_bstr_t(temp_Str), _variant_t((IDispatch*)m_ptrConnection, TRUE), adOpenStatic, adLockBatchOptimistic, adCmdUnknown);// temp_Str是查詢命令
ASSERT(m_ptrRecordset);
if(hr != S_OK)
{
m_ptrConnection->Close();
AfxMessageBox(L"create recordset error!");
return false;
}
if(!m_ptrRecordset->adoEOF)
{
_variant_t varNo = (_variant_t)m_ptrRecordset->GetCollect ((long)0); //得到查詢結果的值
if(varNo.vt!=VT_NULL)
{
MinCount = varNo;
}
}