您的位置:首页 > 数据库 > Oracle

VC++.net使用OCCI连接远程Oracle数据库

2008-03-19 11:42 941 查看
由于项目的需要,需要用C++去连Oracle数据库,Oracle版本为10g,在经过n次错误后终于成功连接。
最开始用ADO连,装上客户端以后,在Oracle Net Manager中设置服务命名,测试连接成功,然后
设置ODBC数据源,测试也成功,ADO连接串写上"DSN=xxx"就能连上了,但是在释放连接时总是出错,
经过多次尝试后放弃,在网上看到Oracle专门为C++提供了连接的接口OCCI,于是尝试采用这种方法。
一、安装Oracle客户端
安装方式选择为管理员。安装完以后设置服务命名。在%ORACLIENTHOME%/NETWORK/ADMIN目录下tnsnames.ora文件记录了服务命名的设置。我的设置如下:

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服务器IP地址
设置完以后在Net Manager中测试连接,成功就OK了。
二、设置VC++.net环境
我用的编译器是VS2003,首先在工具---选项中Project添加包含文件%OracleClientHome%/Oci/include
添加库文件%OracleClientHome%/Oci/lib/msvc/vc71和%OracleClientHome%/Oci/lib/msvc如果是VC6.0的话就
添加%OracleClientHome%/Oci/lib/msvc/vc6。
然后设置项目属性,在编译器---链接中添加lib文件,oraocci10d.lib,之后把oraocci10d.dll文件复制到system32目录下,这个文件在VC71目录下。
第三步在C++----代码生成中设置运行时库为多线程DLL或是多线程调试DLL,注意这一步设置很重要,
没有设置的话会造成getString函数出错。
三、代码

#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就是前面设置的连接串。
测试成功。以上就是所有的设置过程,唉,还是jdbc好连阿。。。

注意,项目属性中运行时库一定要设置为多线程DLL或是多线程调试DLL,否则getString函数就会出错,我在这个问题上也卡了很长时间,单步调试发现是在string对象析购时出错,在网上看到一篇文章得到答案。
原因是由于程序中使用的内存管理多来源于crt提供的例程,而非直接使用操作系统的接口,这些例程都需要维护一些module全局数据(例如维护池、维护空闲块、或者标记已申请的块等等,不同的实现中有不同的作用),当他们被静态连编时,实际上这些“全局数据”就不“全局”了,不同的module各自为政,每份module都有自己的“全局数据”,自身的内存信息不为他人所知,module A的合法内存快自然不可能通得过module B的合法性验证

解决问题的方法有:
1、不要跨module传递c++对象,或者避免释放跨module申请的内存

2、将参与合作的module统统以multithreaded dll方式链入crt库,让他们的“全局”数据真正全局,注意,所有有交互的module都需要动态链入crt。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: