Delphi 12源码版ODAC的编译与Oracle直连

发布时间:2026/9/17 2:43:28
Delphi 12源码版ODAC的编译与Oracle直连
简介Devart.ODAC v12.0.2 for Delphi 12 Athens 完整源码版是一套面向 Delphi/C Builder 开发者的 Oracle 数据库访问组件适合需要直连 Oracle、把控底层细节或定制组件的桌面应用开发者也常用于企业信息系统、报表平台及数据库管理工具的研发。压缩包共 2000 个文件主体为 hpp、pas 等源代码与 dpk、dproj 工程文件辅以 res 资源、html 文档和多种示例整体约 33.9MB。目前已有 262 人学习/下载。资源内置 Source、Demos、Doc、Include、Lib 等目录从组件的单元源码、工程定义到接口头文件、库文件和可运行示例一应俱全开发者可深入阅读源码理解 ODAC 封装的高性能数据访问、连接池管理、事务处理及 PL/SQL 执行等机制的实现细节也可通过示例快速搭建 Oracle 交互程序必要时直接修改组件行为以满足定制需求。整体目录结构清晰、层级完整对希望在 Delphi 12 中高效集成 Oracle 访问能力、或研究商业数据库组件设计思路的开发者具有不错的参考与复用价值。1. 拿源码版ODAC之前先想清楚这三件事在Delphi项目里接Oracle最怕的不是写SQL而是部署环境。客户机房那台Windows Server没有Oracle Client又没有内网镜像你装个ODACOracle Data Access Components还要先搞定权限和路径。Devart这版v12.0.2 for Delphi 12 Athens的完整源码包解压后不是点击下一步到底的安装程序而是一棵可以拿Make.bat直接编译的源码树。Win32 Only这个后缀也说明白它面向32位Windows程序适合稳定能用、不追新鲜的团队。这个资源适合谁第一类是还在用Delphi 10.3、11做Oracle EBS周边工具想正规化连接层而不想给每台现场机器装Oracle Client的工程师第二类是刚学Delphi想通过源码搞明白TOraSession、TOraQuery这些控件到底封装了OCI多少内容从而写出能更好地处理PL/SQL块和事务的程序。我见过有人把整个Source复制进两个项目里改那等于放弃了官方Make.bat的依赖关系不推荐。如果你只是想在本地用ODAC连一个Oracle 12c跑跑查询安装版就够了但如果你要给客户做二次开发、需要追踪OCI调用或者改掉默认连接行为源码版才是唯一可以下手的地方。接下来我不按Readme顺序讲而是按解包、编译、连接、调试的路径走一遍中途标出参数边界和常见报错。2. 解包后先看Make.bat从源码到IDE组件包的完整编译路径2.1 压缩包里每个目录是干什么的打开7z第一眼是Source、Demos、Include、Lib、DbToolsInterfaces、Doc还有ReadmeSrc.html、History.html、FAQ.html。很多人在这一步就去找Setup.exe但源码版不存在这个东西所有交付物都在目录结构里编码好了。下表是我整理的目录用途目录/文件作用编译安装时的用途Source全部.pas源码运行时包和设计时包的工程都在里面这是主要修改和编译目标Demos可运行的示例程序分普通连接、Direct模式、DataSnap等子目录验证编译结果比读文档快IncludeOracle OCI 头文件和接口定义文件只有改到协议层时才需要动DocHtmlDocs、帮助文件含属性、事件索引查询参数定义Lib预生成的.bpl/.dcp输出目录编译后会写入这里给 IDE 提供库路径DbToolsInterfacesDevart 统一数据库接口抽象层ODAC 与其它Dx*控件共用多数据库切换时使用Make.bat批量编译入口脚本最优先打开的文件我一般会先打开History.html看这一版对Delphi 12 Athens的修复再打开ReadmeSrc.html看编译命令。这次源码包带的Make.bat是编译脚本必须手工传目标平台参数它不像安装版那样有图形界面写在批处理里的顺序就代表依赖顺序。2.2 Make.bat的编译开关与执行顺序Make.bat的核心并不是一次性把几十个包全部编完而是按依赖顺序调用子目录里的.dpk。以Win32平台为例通常顺序是先编核心运行时包再编访问层最后编设计时包。命令行上有一个平台参数直接写Win32就是这套源码唯一支持的目标。REM 面向 Delphi 12 Athens (RAD Studio 12) 的 Win32 编译环境 set BDSC:\Program Files (x86)\Embarcadero\Studio\23.0 set ODAC_PATHD:\Libs\ODAC_12\FullSource set PATH%BDS%\bin;%BDS%\lib;%PATH% cd /d %ODAC_PATH%\Source call %ODAC_PATH%\Make.bat Win32第一行指定BDS路径23.0对应Delphi 12 Athens如果你机器上是Delphi 11 Alexandria要改成22.0Delphi 10.4则是21.0。PATH里加上%BDS%\bin是为了让编译器找到dcc32.exe和make.exe。最后用call而不是直接执行Make.bat是确保编译结束后脚本能回到当前命令行方便看错误输出。Make.bat执行时会输出每个包的编译结果。看到.bpl和.dcp生成在Lib\Win32下就算过关。如果提示找不到*.dres或路径字符错误多半是脚本里写死了相对路径你需要把压缩包解压到不带空格的路径比如D:\Libs\ODAC_12\FullSource而不是放在C:\Users\张三\Downloads\ODAC (1)下面。提示如果看到F1026 File not found先检查 ODAC_PATH 是否包含空格或中文。源码版对路径字符很敏感这一条能解决七成编译失败。2.3 把编译好的包安装进Delphi 12 Athens编译通过不等于IDE里能用。设计期组件包dclodac*.bpl要装进IDE的组件列表运行时包odac*.bpl则要加进Library路径否则编译你的项目时会报找不到Ora.pas或单元搜索路径缺失。打开Delphi 12的Tools - Options - Environment Options - Delphi Options - Library在Library path里加入两个目录Source和Lib\Win32。然后在Components - Install Packages - Add里选择你刚生成的dclodac230.bpl版本号随BDS版本变化。如果愿意写注册表也可以用命令行方式在全新环境上批量部署reg add HKCU\Software\Embarcadero\BDS\23.0\Known IDE Packages /v D:\Libs\ODAC_12\FullSource\Lib\Win32\dclodac230.bpl /d Devart Oracle Data Access Components /t REG_SZ /f注意Known IDE Packages控制设计期包列表键名必须是BPL的完整路径值是显示名称。不推荐用reg去遍历覆盖整个键值对反而应该直接打开IDE的Install Packages对话框手工Add因为IDE要把设计期包注册到特定组件页。如果你是为了Debug而编译源码版建议这时就把Lib下预生成的BPL备份到旁边以后每次改完Source就重新Make再安装否则断点根本进不了源码。3. 连接OracleTOraSession参数与其背后的Direct模式3.1 最小的连接代码TOraSession是ODAC的会话入口其它组件都挂在一个Session下。最小连接不丢异常的情况下可以这样写var Session: TOraSession; begin Session : TOraSession.Create(nil); try Session.Options.Direct : True; // 不依赖本地Oracle Client直连TCP Session.Server : 192.168.10.20:1521/ORCL; Session.UserName : scott; Session.Password : tiger; Session.LoginPrompt : False; // 关闭登录框 Session.Connect; WriteLn(Session.Connected, ;, Session.ServerVersion); finally Session.Free; end; end;这段代码的关键是Options.Direct。Direct模式是ODAC的核心特性它不用Oracle官方的OCI客户端栈而是用内部实现的TCP/Net8协议直接与Oracle监听器通信。因此客户机上不需要装Oracle Client也不需要配tnsnames.ora只要网络能到1521端口就行。Server参数可以填两种格式一种是主机:端口/服务名另一种是TNS别名当Direct : False时。ServerVersion在连接成功后返回Oracle版本字符串可以用它来校验连接是否打到了预想实例。如果你确定客户机会安装Oracle Client也可以关闭Direct让ODAC走标准OCI。OCI模式的优势是完整支持Oracle Net高级特性ACL、TCPS、RAC负载均衡劣势是部署时要多带上oci.dll和orannzsbb8.dll。我在一个项目里就是这样生产环境用Direct因为IT禁止装Oracle Client开发环境走OCI模式方便直接用SQL*Plus连同一个库。切换时只需要改Options.Direct和Server的写法其它组件逻辑不用动。3.2 连接池与Session复用连接池可以减少频繁建立Oracle会话的开销。ODAC中位于Session.Options.Pooling下面几个参数是实际调优会碰到的参数作用我常用的值Pooling是否启用连接池TruePoolSize池内最大连接数20PoolTimeout空闲连接超过该秒数被回收60ConnectionTimeout创建新连接超时30代码开启连接池OraSession.Options.Pooling : True; OraSession.Options.PoolSize : 20; OraSession.Options.PoolTimeout : 60; OraSession.Options.ConnectionTimeout : 30; OraSession.Connect;连接池生效后连续执行Disconnect / Connect会复用物理连接但要注意如果程序内部修改了Session.Options.Direct或Server的值池内连接会被视为不同Key重建这是新人的常见误用。Demos里的DataPool示例展示了如何配合ChangeConnection释放连接。3.3 事务与PL/SQL执行Oracle事务控制对ODAC来说是个三件套OraSession.StartTransaction; try OraQuery1.Execute; OraSession.Commit; except OraSession.Rollback; end;StartTransaction之后OraQuery1等数据集上的DML不会自动提交直到Commit或Rollback。ODAC还支持IsolationLevel参数ilReadCommitted是默认ilSerializable用于要求严格一致性的批处理。PL/SQL块可以直接用TOraSQL执行适合雏形验证OraSQL1.SQL.Text : BEGIN UPDATE emp SET sal sal * 1.1 WHERE deptno :P_DEPTNO; :P_CNT : SQL%ROWCOUNT; END;; OraSQL1.ParamByName(P_DEPTNO).AsInteger : 20; OraSQL1.Execute; ShowMessage(更新行数: OraSQL1.ParamByName(P_CNT).AsString);这里P_CNT要事先声明参数方向为pdInputOutput否则拿不到行数。许多新手在Delphi里直接拼SQL遇到带分号的匿名块就报错其实正确的做法是保留Oracle原生的BEGIN...END;结构ODAC会原样发到服务端。如果存储过程里返回了Oracle对象类型那还要配合TOraObject使用这部分我在第4章展开。4. 从Demos到生产查询、存储过程与源码级定制4.1 用TOraQuery和DBGrid搭一个查询页这里给一个典型查询OraQuery1.Session : OraSession1; OraQuery1.SQL.Text : SELECT * FROM emp WHERE deptno :DEPTNO AND sal :SAL; OraQuery1.ParamByName(DEPTNO).AsInteger : 10; OraQuery1.ParamByName(SAL).AsCurrency : 2000; OraQuery1.Open; DataSource1.DataSet : OraQuery1; DBGrid1.DataSource : DataSource1;Open前ODAC会为带参数的SQL做Prepare所以参数类型不要乱用AsString去绑定数字字段否则Oracle执行计划可能退化成隐式转换。TOraQuery自带FetchAll控制默认是True一次性拉回所有记录查询大结果集时可以设FetchAll : False并配合FetchRows : 100但要注意此时RecordCount不可靠数据窗口受KeyFields和ReadOnly控制。Oracle 12c里绑定变量对执行计划很敏感。ODAC给TOraQuery开了Options.PrepareOnce默认情况下同一会话只Prepare一次第二次Open会复用游标如果SQL文本被动态拼接成每次都不同的字符串这个优化就失效了。所以生产项目里要求所有查询都走参数绑定尽量别用字符串拼接。4.2 调用存储过程与Oracle对象类型TOraStoredProc是ODAC封装存储过程的主力OraStoredProc1.Session : OraSession1; OraStoredProc1.StoredProcName : COMMON_PKG.GET_EMP_LIST; OraStoredProc1.ParamByName(P_DEPTNO).AsInteger : 10; OraStoredProc1.ParamByName(P_CURSOR).DataType : ftCursor; OraStoredProc1.Open;注意输出游标参数用ftCursorOpen后才可以把数据接到DBGrid。对于返回多个游标的包ODAC的TOraStoredProc还允许用NextRecordSet反复取下一个结果集适合那种假装不知道哪个游标有数据的旧存储过程。Oracle对象类型例如TYPE emp_type IS OBJECT(...)ODAC支持映射为TOraObject在数据集上设置Options.ObjectFields后通过FieldValue取值。这个功能在直接读复杂视图时很好用但对象嵌套超过两层时需要写对象描述器属于进阶中的进阶。4.3 在源码里加日志自定义组件行为这一节体现“完整源码版”价值。比如我想记录每次TOraSession.Connect执行的时间不必再包一个AfterConnect事件而是直接改Source。源文件中定位TOraSession.Connectprocedure TOraSession.Connect; begin // 自定义连接前输出目标服务器不要打口令 OutputDebugString(PChar(ODAC Connect - Server)); inherited Connect; OutputDebugString(PChar(ODAC Connected, version ServerVersion)); end;重新执行第2章的Make.bat Win32然后把生成的BPL重新装进IDE之后所有使用该组件的工程都会自带这份日志。这个做法在需要排查DBA绕环境时比在调用层写try/expose更接近根因。当然要注意如果只是改了自己工程里的引用不想动全环境的包也可以把改动后的单元加到工程里但那样会引入源码重复容易在包单元和工程单元之间产生标识冲突。推荐还是走BPL升级。调试时配合Delphi的Debug - Windows - Event Log能看到OutputDebugString输出。这个日志会在连接池复用旧连接时也触发因为底层还是调用了Connect逻辑如果想区分是否真正新建物理连接可以在Connect内再打印Session.Pooling和当前ActivePoolSize值。5. 验证与排错从“组件已安装”到“跑通一个事务”5.1 用Demos用例验证编译结果安装完组件后直接用Demos目录下的Examples就行。以Demos\Oracle\SQLInfo为例编译运行后填上连接串能拉出库表结构就说明BPL注册没问题。如果运行时报找不到OraDac*.bpl把Lib\Win32加进系统的PATH或把BPL复制到EXE同目录。这一步能过滤掉八成“装完点不亮”的故障。5.2 Open Dataset错误与处理报错“cannot perform this operation on an open dataset”时多半和TOraQuery.Active状态没关掉有关。ODAC对Open状态下的SQL修改管得比BDE严解决方法是if OraQuery1.Active then OraQuery1.Close; OraQuery1.SQL.Text : SELECT ...; OraQuery1.Open;如果你是在AfterOpen事件里直接调DataSet.EnableConstraints也可能在打开状态中触发同类错误。ODAC的做法是统一先Close再改SQL。我第一次从BDE迁过来时总在FieldByName前忘了Close后来把判断封装成公用函数现在每个SQL变更入口都过了这层保护。5.3 证书、时区与Win32的边界Oracle 19c以上默认启用TLSODAC连接时会报“server certificate invalid or not present”。严格做法是在TOraSession.Options里配置Oracle WalletSession.Options.SSL : True; Session.Options.WalletPath : D:\oracle\wallet;如果只是内网开发库可以在SSLOptions里设置SSLServerCertVerify : False跳过证书校验但这不该出现在生产代码里。此外时区问题ODAC服务器端返回的TIMESTAMP WITH TIME ZONE受Session.Options.TimeZone影响建议明确指定为目标库时区避免默认取系统时区导致的数据偏移。最后说Win32边界。这套Full Source Only面向32位Windows程序Delphi 12 Athens本身能生成Win64包但本套组的BPL和DCP只在Win32目标下编译。若你的项目必须是Win64一个折中是写一个32位的中间服务把ODAC数据访问封装成HTTP或gRPC另一个是等官方出64位补丁。在还没有明确需求前我的建议是保持Win32Oracle客户端生态对它的兼容反而更稳。调试时如果还想追到协议层用ODAC自带的OraNet网络监控在Session.Options.Net里把日志级别调到lmDebug再配合dbms_application_info打标记到V$SESSION就能把每个会话的SQL串到业务代码上。本文还有配套的精品资源点击获取