OO4O 簡介 ( Oracle Object For Ole ) Oracle 所提供的 Native OLEDB Driver , 效能比 ADO 快 -------------------------------------------------- 方法 1: 使用 ORADC 設定使用元件 Oracle Data Control 設定 ORADC 的 Connect , DatabaseName 及 RecordSource 後
ORADC.Connect="UserID/Password" ORADC.DataBaseName="DatabaseAliasName" ORADC.RecordSource="TableName或SQL" 之後即可 oraDC.Recordset 來做資料的處理 ----------------------------------------------------- 方法 2: 使用 OracleInProcServer 物件來做 透過 LateBinding 來 CreateObject
Set oraSession = CreateObject("OracleInProcServer.XoraSession") '--- 建立 Session 物件 Set oraDatabase = oraSession.OpenDatabase(DatabaseAlias,"UserID/Password", 1) '--- 建立 Database 物件 Set oraRecordset = oraDatabase.CreateDynaset(SQL, 4) '--- 建立 Recordset 物件
之後即可 oraRecordset 來做資料的處理
VS.Net 可使用 ODP.Net ( Oracle Data Provider 4 .Net )
============================================================================
我在asp中使用oracle的OO4O,在oracle8和oracle8i中都正常,但在oracle9i却出错 请大虾指教 dim cn dim oracn set cn=server.CreateObject("oracleinprocserver.xorasession") set oracn=cn.dbopendatabase("VMINFO","samples/samples",0) 最后一行出错,错误信息 unable to make connectiong ora-12638:身份证明搜索失败 我的环境 :win2000 oracle9I oracle object for OLE 已安装 wEB服务器和数据苦在同一台机器上 使用samples/samples@VMINFO可以登陆 ----------------------- another thing to try is to turn off Oracle's NT authentication: Try setting the following in the sqlnet.ora file on the server:
sqlnet.authentication_services=(none) ----------------------- 谢谢,已经解决,顺便问一下 sqlnet的几个参数的作用 ----------------------- SQLNET.AUTHEN****** 是用来设置认证的,参看 ================================================================
Oracle 8.1.7数据库服务器上OO4O不能执行的问题: 现象: 1。用OO4O连接数据库的VB程序,在客户机上可以正确执行,但在Oracle 8.1.7的数据库服务器(Win2K)上却无法执行 2。用OO4O连接数据库的ASP程序,在其它装了IIS的服务器上可以正确执行,但在Oracle 8.1.7的数据库服务器上却无法
执行 解决方法: 1。如果VB程序不能执行,重新安装OO4O即可,启动Oracle Universal Installer,然后选择Oracle Object for Ole 2。方法一: ASP连接数据库,不能像VB程序那样, 用下面的CreateObject来创建OraSession对象 (也许有其他方法可以实现Session对象的直接创建,各位有兴趣可以研究一下): Set OraSession = Server.CreateObject("OracleInProcServer.XOraSession") Set OraDB = OraSession.OpenDatabase(dbAlias,UserName/Password,0) 而是应该在虚拟目录的Global.asa文件中写如下语句:
<OBJECT RUNAT=Server SCOPE=Application ID=OraSession PROGID="OracleInProcServer.XOraSession"></OBJECT>
在Global.asa的Application_OnStart事件过程中增加下列语句(如果没有Application_OnStart事件过程,则需添加此
过程):
OraSession.CreateDatabasePool 1,40,200,dbAlias, UserName/Password, 0 然后在ASP程序中用下列方法打开数据库:
Set OraDB = OraSession.GetDatabaseFromPool(10) 注意:修改Global.asa后必须重新启动WWW服务。上述方法中各参数的意义请参考 Oracle Object for OLE Help 帮助文
件 方法二:
可以通过修改Oracle的用户认证方式,而不修改ASP程序的办法来解决。 但出于安全性的考虑,修改用户认证方式有时是不允许的。
修改方法如下:
将d:\oracle\ora81\network\admin\sqlnet.ora中的 sqlnet.authentication_services = (NTS)
改为 sqlnet.authentication_services = (none) 以后ASP程序即可正常执行。 ========================================================================= 在ASP中通过oo4o连接Oracle数据库的例子
下面这段代码能够显示,当前用户所能够看到的所有的用户和表,有兴趣的, 可以把每个表的内容加上
<% Dim objOraSession,objOraDb Dim strDbUser,strDbPwd,strDbConn Call ConnectDB() Sub ConnectDB() '连接数据库 On Error Resume Next strDbUser = "tmpUser" '连接用户名 strDbPwd = "rt45ps1w" '用户密码 strDbConn = "sun450" '连接字符串 Set objOraSession = Server.CreateObject("OracleInProcServer.XOraSession") Set objOraDB = objOraSession.OpenDatabase(strDbConn,strDbUser & "/" & strDbPwd,0) If Err.Number>0 then Response.Write "<font color=red>错误 :" & err.description & "</font>" response.end End if End Sub Sub EndDB() Set objOraDB = Nothing Set objOraSession = Nothing End Sub Function getTableList(str) Dim strSql,strTmp Dim objRs strSql = "Select at.table_name as tname,au.username as uname from all_tables at,all_users au Where
au.username=at.owner order by au.username" Set objRs = objOraDb.DbCreateDynaset(strSql,0) While Not objRs.Eof strA = objRs("uname") & "." & objRs("tname") If str=strA then strTmp = strTmp & "<option selected>" & strA & "</option>" Else strTmp = strTmp & "<option>" & strA & "</option>" End if objRs.MoveNext Wend Set objRs = Nothing getTableList = strTmp End Function %> <form name=form1 action="index.asp" method=POST target="main"> <table width="100%" border=0 align="center"> <tr><td> All Tables : <select name="tb"> <%=getTableList(tblName)%> </select> <input type=hidden name="submitc" value="view"> <input type=submit name="submit" value="View Data"> <font color=red>(<%=strDbUser & "/" & strDbPwd & "@"
& strDbConn%>)</font> </td></tr> </table> </form>
============================================================ 使用oo4o时Session没自动释放 问题表现: 1. 程序使用 oo4o 连 Oracle 数据库,连接1段时间大约2-3小时后,客户端死掉,执行 ODatabase.ExecuteSQL方法返回 101 错误。此时,客户端使用TOAD连库,会报错 错误代码为 04031。
2. 当客户端程序执行其子线程时,不管怎么调用OSession和ODatabase的Close方法, 从TOAD中可以看到客户端机器连过来的Session一直都没有消掉。
3. 需要杀掉所有线程或者重新启动程序,才能继续用客户端读库和使用TOAD连库。
原因查找: 1. 焦点锁定在 Oracle服务器内的存储过程上,客户端调用库的存储过程时用到了游标。 2. 模拟实验1中,如果调用使用游标的存储过程,则Session关不掉。如果调用不使用游标的 存储过程,则Session可以关掉。模拟实验2中,如果在客户端调用游标时设置游标的属性 则,也能够实现Session的自动关闭。 该语句为 “ curParam.SetDynasetOption(ODYNASET_NOCACHE)? ”
{//。。。。。 OParameter curParam ; ODynaset curDynaset; curParam.SetDynasetOption(ODYNASET_NOCACHE);? //Important curParam.GetValue(&curDynaset); //。。。。。。 }
3. 继续查,发现问题在对数组边界的处理上。因为oo4o的OParameterCollection起始值比较特别。 当使用for循环调用 Param.Remove(i)时,其范围应该是 for (i = 1; i < nCount+1; i++), 而不是 for (i = 0; i < nCount; i++)。而之前使用的游标恰好在最后1位,因此没有被Remove。 所以误以为是因为游标或者其参数的问题。其实是数组边界问题。
参考: 1. http://skywheel.sarang.net/docs/Oracle/10g/win.101/b10119/o4c00051.htm 2. http://skywheel.sarang.net/docs/Oracle/10g/win.101/b10119/o4c00044.htm 3. http://skywheel.sarang.net/docs/Oracle/10g/win.101/b10119/o4c00052.htm ====================================================================== http://junglesong.yculblog.com/post.934359.html 从简化oo4o的数据库访问过程到工厂模式
Junglesong 发表于 2005-10-21 17:04:06
大家应该还记得0040访问数据库的常用方式,是用SQL语句产生一个记录集OraDynaset,再对 此记录集进行遍历操作,取出需要的数据。如果这样的代码混杂在程序的主要业务 逻辑中,无疑会影响程序的可读性,代码也会有不必要的重复,所以我们可以将上 述过程用一个函数包装一下,程序如下:
‘// 函数注释:传入一个Sql语句,得到一个二维数组,数组元素类型为String。 Public Function get2dArrayBySql(strSql As String) '// 建立记录集 Dim OraDynaset As Object Set OraDynaset = gOraDatabase.DbCreateDynaset(strSql, ORADYN_READONLY) '// 建立并调整数组的大小 Dim arrayRetval() As String ReDim arrayRetval(OraDynaset.recordcount, OraDynaset.fields.Count - 1) '// 遍历记录集将数据传入数组 Dim i, j As Integer While Not OraDynaset.EOF For j = 0 To OraDynaset.fields.Count - 1 arrayRetval(i, j) = mfChgNull(OraDynaset.fields(j).Value) Next i = i + 1 OraDynaset.MoveNext Wend '// 将数组返回 get2dArrayBySql = arrayRetval End Function
调用例子如下:
Dim arrayRowBody() As String arrayRowBody = get2dArrayBySql(strSql)
这样,程序的业务逻辑就和数据库的具体访问过程分开了,达到了高内聚,低耦合 的目的。如果程序使用的数据库发生改变,只需变更get2dArrayBySql的访问过程 就可以了,业务逻辑中的代码无需改变。
上述函数还需要mfChgNull的辅助,当数据为空时可以传回一个零长度字符串。
Public Function mfChgNull(varData As Variant) As String On Error GoTo errorproc
If (IsNull(varData)) Then mfChgNull = "" Else mfChgNull = CStr(varData) End If Exit Function errorproc: mfChgNull = "" End Function
在完全面向对象(c++,java,C#,vb.net)的语言中,代码还可以进一步发展,比如 程序需要访问多种数据库,但业务逻辑都是一样的,这时可以制作一个数据库访 问的基类,在其中实现数据库访问的各种接口函数(c++是纯虚函数,java是接口 ),然后在此基类上实现具体访问各种数据库的子类,具体由哪个类来访问具体的 数据库由一个工厂类来判断,下面依次讲解:
假设基类名为DbAccessBase, 访问Oracle数据库的子类名为OracleDbAccessBase 访问SqlServer数据库的子类名为SqlServerDbAccessBase 访问MySql数据库的子类名为MySqlDbAccessBase
他们都继承自DbAccessBase,类继承图如下 DbAccessBase<-------OracleDbAccessBase | |___SqlServerDbAccessBase | |___MySqlDbAccessBase
DbAccessBase有一个接口函数get2dArrayBySql,三个子类都分别实现了这个接口函数.
下面用伪代码来说明具体实现
DbAccessBase dbAccess;
if(数据库类型==Oracle数据库){ dbAccess=new OracleDbAccessBase(); } else if(数据库类型==SqlServer数据库){ dbAccess=new SqlServerDbAccessBase(); } else{ dbAccess=new MySqlDbAccessBase(); }
以后直接使用dbAccess这个实例来访问数据库即可,业务逻辑无需关注数据库的详 细情况.
工厂类就是用来将刚才的代码包装一下,它的具体结构如下:
class DbAccessFactory{ public static gettDbAccessInstance(String 数据库类型){ DbAccessBase dbAccess; if(数据库类型==Oracle数据库){ dbAccess=new OracleDbAccessBase(); } else if(数据库类型==SqlServer数据库){ dbAccess=new SqlServerDbAccessBase(); } else{ dbAccess=new MySqlDbAccessBase(); }
return dbAccess; } }
然后我们的调用过程就简化成如下代码:
DbAccessBase dbAccess=DbAccessFactory.gettDbAccessInstance(数据库类型)
如果需要增添一种数据库访问,实现DbAccessBase的一个子类,并在DbAccessFactory中多加一 个判断就可以了,其它都不需要修改.
大道至简,Hibernate对多数据库的访问实现不过如此. ====================================================================
|