??????? 由于項目的需要,需要用C++去連Oracle數(shù)據(jù)庫,Oracle版本為10g,在經(jīng)過n次錯誤后終于成功連接。
?????? ?最開始用ADO連,裝上客戶端以后,在Oracle Net Manager中設(shè)置服務(wù)命名,測試連接成功,然后
設(shè)置ODBC數(shù)據(jù)源,測試也成功,ADO連接串寫上"DSN=xxx"就能連上了,但是在釋放連接時總是出錯,
經(jīng)過多次嘗試后放棄,在網(wǎng)上看到Oracle專門為C++提供了連接的接口OCCI,于是嘗試采用這種方法。
??????? 一、安裝Oracle客戶端
??????????????? 安裝方式選擇為管理員。安裝完以后設(shè)置服務(wù)命名。在%ORACLIENTHOME%\NETWORK\ADMIN目錄下tnsnames.ora文件記錄了服務(wù)命名的設(shè)置。我的設(shè)置如下:
???????????????

ORCL_192.168.0.3?=
??(DESCRIPTION?=
????(ADDRESS_LIST?=
??????(ADDRESS?=?(PROTOCOL?=?TCP)(HOST?=?192.168.0.3)(PORT?=?1521))
????)
????(CONNECT_DATA?=
??????(SID?=?orcl)
??????(SERVER?=?DEDICATED)
????)
??)

ORCL?=
??(DESCRIPTION?=
????(ADDRESS_LIST?=
??????(ADDRESS?=?(PROTOCOL?=?TCP)(HOST?=?192.168.0.3)(PORT?=?1521))
????)
????(CONNECT_DATA?=
??????(SERVICE_NAME?=?ORCL_192.168.0.3)
????)
??)

其中192.168.0.3為遠程Oracle服務(wù)器IP地址
設(shè)置完以后在Net Manager中測試連接,成功就OK了。
????????二、設(shè)置VC++.net環(huán)境
??????? 我用的編譯器是VS2003,首先在工具---選項中Project添加包含文件%OracleClientHome%\Oci\include
添加庫文件%OracleClientHome%\Oci\lib\msvc\vc71和%OracleClientHome%\Oci\lib\msvc如果是VC6.0的話就
添加%OracleClientHome%\Oci\lib\msvc\vc6。
然后設(shè)置項目屬性,在編譯器---鏈接中添加lib文件,oraocci10d.lib,之后把oraocci10d.dll文件復(fù)制到system32目錄下,這個文件在VC71目錄下。
第三步在C++----代碼生成中設(shè)置運行時庫為多線程DLL或是多線程調(diào)試DLL,注意這一步設(shè)置很重要,
沒有設(shè)置的話會造成getString函數(shù)出錯。
??????? 三、代碼
???????

#include? " stdafx.h "
#include?
< occi.h >
using ? namespace ?std;
using ? namespace
?oracle::occi?;
int
?main()?
{
????Environment
* ?env = Environment::createEnvironment( " ZHS16GBK " ,? " UTF8 "
);
????
// Environment?*env=Environment::createEnvironment(Environment::DEFAULT);


????
string ?mc;
????
{
????????Connection?
* conn? = ?env -> createConnection( " system " ,? " system " ,? " orcl_192.168.0.3 "
);
????????
????????
try

????????
{
????????????Statement?
* stmt? = ?conn -> createStatement( " select?*?from?test1 "
);

????????????ResultSet?
* rs? = ?stmt ->
executeQuery();
????????????
while (rs -> next()? == ? true
)
????????????
{
????????????????mc
= rs -> getString( 1
);
????????????????cout?
<< ?mc? <<
?endl;
????????????}

????????????stmt
-> closeResultSet(rs);
????????????conn
->
terminateStatement(stmt);
????????}

????????
catch ?(SQLException?e)
????????
{
????????????cout
<<
e.what();
????????}

????????env
-> terminateConnection(conn);
????}

????Environment::terminateEnvironment(env);
????system(
" pause " );
????
return ? 0
;
}

orcl_192.168.0.3就是前面設(shè)置的連接串。
測試成功。以上就是所有的設(shè)置過程,唉,還是jdbc好連阿。。。

注意,項目屬性中運行時庫一定要設(shè)置為多線程DLL或是多線程調(diào)試DLL,否則getString函數(shù)就會出錯,我在這個問題上也卡了很長時間,單步調(diào)試發(fā)現(xiàn)是在string對象析購時出錯,在網(wǎng)上看到一篇文章得到答案。
??????? 原因是由于程序中使用的內(nèi)存管理多來源于crt提供的例程,而非直接使用操作系統(tǒng)的接口,這些例程都需要維護一些module全局數(shù)據(jù)(例如維護池、維護空閑塊、或者標記已申請的塊等等,不同的實現(xiàn)中有不同的作用),當他們被靜態(tài)連編時,實際上這些“全局數(shù)據(jù)”就不“全局”了,不同的module各自為政,每份module都有自己的“全局數(shù)據(jù)”,自身的內(nèi)存信息不為他人所知,module A的合法內(nèi)存快自然不可能通得過module B的合法性驗證

解決問題的方法有:
1、不要跨module傳遞c++對象,或者避免釋放跨module申請的內(nèi)存

2、將參與合作的module統(tǒng)統(tǒng)以multithreaded dll方式鏈入crt庫,讓他們的“全局”數(shù)據(jù)真正全局,注意,所有有交互的module都需要動態(tài)鏈入crt。