简介:Devart ODAC v12.0.2 for D6-D13 Full Source 是一份面向 Delphi 6 至 Delphi 13 开发者的 Oracle 数据访问组件完整源代码包,旨在帮助需要高效连接与操作 Oracle 数据库的企业级应用开发人员,通过集成 ODAC 组件实现高性能、稳定的数据交互。压缩包共包含 2000 个文件,大小约 9.77MB,涵盖 439 个 hpp 头文件、265 个 dpk 与 240 个 dproj 工程配置、183 个 pas 源文件以及 49 个 dfm 窗体定义等,结构上覆盖了组件库的声明、编译脚本、源码与界面资源,便于在对应 Delphi 版本中直接编译加载。目前已有 180 人学习下载,适合具备一定 Delphi 基础、需要深度定制数据访问层或希望研究 Devart 组件实现原理的开发者。通过源码可深入理解 ODAC 对 Oracle 高级特性(如 12c 新特性)的封装方式,并依据项目需求自行调整组件行为,从而减少重复造轮子。同时,包内的 bat 编译脚本与 sql 示例脚本也有助于快速完成组件构建和连接验证,提升数据库应用的整体开发效率。
1. 拿到这个包先明白:Devart.ODAC 是什么、能解决什么问题,适合谁
如果手头还有一批 Delphi 写的 Oracle 业务系统,此刻正被“客户端没装 Oracle、还得带一套 tnsnames 配置到处跑”折磨,那么这个标题里的 Devart.ODAC v12.0.2 就是那味解药。它是一个面向 Delphi 6 到 Delphi 13.1 的 Oracle 数据访问组件包,Full Source 版本意味着你能拿到全部源码,自己改、自己编译、装进 IDE,而不是拿着黑盒运行时提心吊胆。这篇笔记适合谁?给还在维护老 Delphi 项目、以及要在新版本 Delphi 里重建 Oracle 数据层的你。
它真正解决的问题有三个:第一,Direct 模式可以免装 Oracle 客户端,直接走 TCP/IP 连数据库,部署现场少一半麻烦;第二,同一套源码能跨多个 Delphi 版本编译,公司里有 D7 老工程和 Delphi 13.1 新工程都能用;第三,Full Source 让你能查到底层实现,真出了怪问题不至于全信黑匣子。网上相关热词里能看到很多人问“Delphi 最新版能不能用老控件”“FireMonkey 源码和 VCL 控件怎么选”,这个包恰好只回答其中一半:它是 VCL 组件,不碰 FireMonkey UI,专注把 Oracle 访问这层做好。接下来我从安装开始,一步步讲清楚怎么把这东西用起来、坑在哪、值不值得长期投入。
2. 从 7z 到 IDE 面板:安装与编译源码的两种路线
2.1 解压后先看目录结构:别急着双击安装脚本
拿到 .7z 文件,第一步不是解压后立刻找安装 exe,而是先看目录里摆了什么。常见做法是解压后能看到 Source、Demos、Install、Docs 这四类目录,Source 下按 Delphi 版本分了子目录,Install 里放的是各版本的注册脚本。先花五分钟把目录结构捋一遍,能避免后面装错包。
我要提醒一句:如果你只打算用现成的运行时,直接跑 Install 里的脚本就行;但如果你冲着 Full Source 来,想把组件源码挂进 IDE 的 Library 路径,那结构必须看仔细。Source 目录里通常有 run-time 和 design-time 两套包,前者是组件实现,后者是让组件出现在 IDE 面板上的设计时代码。这两套的顺序搞反了,面板上就什么都看不到。别问我怎么知道的——我第一次装的时候直接双击了 Install 里最大的那个 .bat,结果 IDE 面板干干净净,源码路径也没挂上。
顺便说个版本对应的事。标题里写了 for D6-D13,实际操作时不要默认“我的 Delphi 13.1 一定能装”。装之前打开 Install 目录确认有没有对应版本号子目录,没有就切到手动编译路线。老控件包对 IDE 版本敏感,这一步省了后面全是玄学错误。
2.2 标准安装:用 Install 向导注册到 IDE
最稳妥的标准安装方式是运行 Install 目录里对应版本号的安装脚本。先关掉 Delphi IDE,然后用管理员身份运行。脚本会做三件事:把 run-time 包编译好、把 design-time 包注册进 IDE、把源码路径写入 Library 搜索路径。如果你只想尽快跑通,这是最短路径。
这里给一个手动执行安装脚本的参考命令,用命令行跑比双击更容易看到报错输出:
REM 以管理员身份运行,先进入 Install 目录 cd /d D:\devart\odac\Install REM 假设当前 Delphi 版本是 13.1,执行对应安装脚本 Install_D13.bat命令本身不复杂,但有几个参数值得解释。Install_D13.bat 里通常会调用 dcc32 编译全部 dpk 文件,脚本默认使用 Release 配置;如果 IDE 开着,注册 design-time 包那一步会失败,所以必须先关 IDE。另外有些版本脚本默认只装到当前用户,换账号登录后组件会消失,这不算 bug,重新跑一遍脚本就行。
装完后打开 Delphi,Component 菜单下的 Install Packages 列表里如果能看到 Devart ODAC 条目,就说明设计期包注册成功了。接着打开 Tools > Options > Library,确认 Source 路径已经被加进去。这两处都对了,才算是装完了。
2.3 手动编译 Full Source:需要打开的包文件与顺序
标准安装有时会翻车,比如脚本里预设的路径和你机器上的不一致,或者你的 Delphi 版本比脚本支持的更新。这时候就走手动编译路线。Full Source 的价值也在这一步体现:你能自己控制编译顺序和选项。
I一般先编译 run-time 包,再编译 design-time 包。用命令行做更可控:
REM 先编译运行时包:不带 DCL 前缀的 .dpk 文件 dcc32 -B -Q -U..\Source -R..\Lib -DDEBUG Ora.dpk REM 再编译设计时包:带 DCL 前缀的 .dpk 文件 dcc32 -B -Q -U..\Source DclOra.dpk参数说明:-B 是强制重建,编译完整源码时必须加,否则可能用了旧 obj;-U 指定源文件搜索路径,这里指向 Source 目录;-R 指定资源文件路径;-DDEBUG 可以提前把调试符号编进去。编译 run-time 包时能看到一堆 pas 文件被挨个编译,如果报错停在某个文件上,先看是不是路径少了 Source 子目录。
设计时包编译完成后,在 IDE 里选 Component > Install Packages > Add,把生成的 .bpl 文件加进去。这里有个容易踩的地方:design-time 包编译依赖 run-time 包先装好,顺序反了会报“找不到 xx.dcp”。手动编译的好处是报错直观,坏处是要自己管依赖顺序。第一次搞不定时,我建议直接在 IDE 里打开 Dcl 开头的 .dpk 文件,右键选择安装,IDE 会自动补依赖。
Full Source 手动编译这条路,适合三种人:IDE 版本不在脚本支持列表里的、需要改源码加日志的、以及被标准安装脚本坑过不止一次的。如果只是为了写业务代码,标准安装足够。
3. 落地第一步:用 ODAC 组件连上 Oracle 的三种方式
3.1 走 OCI:复用 Oracle 客户端连接
ODAC 最传统的工作方式是走 OCI 模式,也就是调用 Oracle 官方客户端库。这种模式下,TOraSession 本质上是替你封装了 OCI 调用,连接串写法跟在 SQL*Plus 里几乎一样。适合那些现场已经装了 Oracle 客户端的场景,你不用改变任何部署习惯。
OCI 模式连接有几个先决条件:客户端目录里要有 tnsnames.ora,并且环境变量 TNS_ADMIN 指到了正确位置。连接字符串可以直接写 TNS 别名,也可以写成 host:port/service_name 的形式。前者依赖 tnsnames 解析,后者不依赖。我一般建议用后者,少一个文件就少一个故障点。
下面是最小连接代码:
// OCI 模式连接:前提是本机已经装好 Oracle 客户端 OraSession1.Options.Direct := False; // 关闭直连模式 OraSession1.ConnectString := '192.168.10.20:1521/ORCL'; OraSession1.Username := 'scott'; OraSession1.Password := 'tiger'; OraSession1.Connect;这段代码里最关键的是把 Options.Direct 设为 False,只要不设或设错,组件就会按直连模式解析 ConnectString,导致“TNS 名字解析失败”一类的错误。ConnectString 如果写成 TNS 别名,就需要 tnsnames.ora 可被正常读取;写成 IP 和端口形式,则完全绕开 tnsnames。用户名密码分开传,是为了方便从外部配置文件读取。
OCI 模式最大的优势是跟数据库行为对齐,Oracle 的各种高级特性和新版数据库兼容性最好;最大的劣势是部署时要连带客户端一起装。批量交付给几十台电脑时,每个现场都得处理 Oracle 客户端版本,那是真头疼。所以只用在这种场景:数据库版本太新,ODAC 直连支持跟不上,或者现场已经天然有完整客户端环境。
3.2 走 Direct:免装 Oracle 客户端的本地直连
Direct 模式是 ODAC 最吸引人的卖点:组件自己实现了一套 Oracle 网络协议,不需要本机安装任何 Oracle 客户端。部署时只需要把可执行文件和几个 DLL 放在一起,连环境变量都不用配。对做甲方现场交付的朋友来说,这省掉了整整一类问题。
Direct 模式的连接参数比 OCI 模式更讲究。因为不走 tnsnames,你必须在代码里明确写出主机地址、端口、服务名或实例名,而且有两个大小写敏感的地方我吃过亏:服务名和实例名的解析规则不一样。Oracle 12c 以后默认是用 SERVICE_NAME,很多老代码里习惯写 SID,这在 Direct 模式下经常连不上。
// Direct 模式连接:不需要本机安装 Oracle 客户端 OraSession1.Options.Direct := True; OraSession1.ConnectString := 'scott/tiger@192.168.10.20:1521/ORCL'; OraSession1.Connect;这段代码里 ConnectString 用了一个完整格式:用户名/密码@主机地址:端口/服务名。ODAC 解析这种格式时,会自动识别到 Direct 模式并走 TCP/IP。如果你把用户名密码写在这里,组件内部优先使用这里的值,OraSession1.Username 和 Password 属性可以不设。但为了代码可读性,我仍然建议显式设置 Username 和 Password,连接串里只写 @ 后面的部分。
Direct 模式连接失败时,报错信息里最常见的两句话是“ORA-12541: TNS:no listener”和“ORA-12514: TNS:listener does not currently know of service”。前者是端口写错或数据库没开监听,后者是服务名写错。排查时先 telnet 一下主机端口通不通,再用 Oracle 的 lsnrctl status 看可用的服务名,基本就能定位。直连虽然省了客户端,但排错信息比 OCI 少一层,你得更懂网络。
3.3 最小可运行代码:TOraSession 连接参数怎么填
不带窗体的最小示例更实用,很多控制台脚本和数据迁移工具都用这个模式。创建 TOraSession 实例、设置参数、 Connect,全部在代码里完成。这种写法也适合做单元测试。
// 最小可运行演示:无窗体,直接用 TOraSession 连接 var Sess: TOraSession; begin Sess := TOraSession.Create(nil); try Sess.Options.Direct := True; Sess.Username := 'scott'; Sess.Password := 'tiger'; Sess.Server := '192.168.10.20:1521/ORCL'; Sess.Connect; if Sess.Connected then // 连接成功后可以执行 SQL Sess.Disconnect; finally Sess.Free; end; end;这段代码里有三个参数要讲清楚。Options.Direct 决定走什么协议,True 就是直连,False 走 OCI。Server 在 Direct 模式下必须写完整的 host:port/service_name;在 OCI 模式下则填 tnsnames 里的网络服务名。Username 和 Password 不需要解释,但要注意它们只在 Connect 时读取一次,运行中修改不会生效。
还有一点容易被新手误解:TOraSession 本身不执行 SQL,它是会话管理器。真正干活的是 TOraQuery、TOraStoredProc 这些子组件,Session 只是它们的容器和连接提供者。所以最小验证程序里,连接成功后还应该建一个 TOraQuery 执行 SELECT 1 FROM DUAL,才算真正把链路打通。只看 Sess.Connected 为 True,有时会误判——直连模式下握手成功但后续 SQL 解析有问题的情况,我遇到过不止一次。
4. 这几个坑我踩过:版本不匹配、源码编译失败与连接异常排查
4.1 现象:安装脚本跑完,IDE 面板里没有任何 ODAC 组件
这是最让人上火的问题之一。脚本运行没有报错,但打开 Delphi 的工具面板,搜不到任何 TOraSession、TOraQuery 组件。
原因多半是安装脚本只编译了 run-time 包,没有把 design-time 包注册进 IDE;或者脚本识别错了 Delphi 版本,把 D10 的包装进了 D13 的 IDE。判断方法很简单:打开 Component > Install Packages,看列表里有没有 Devart ODAC 条目。没有就是设计期包没装进去。
解决方法是手动安装设计期包。在 IDE 里打开 DclOra.dpk 文件,右键选 Compile,再右键选 Install;或者用前面命令行方式先编译出 .bpl,再通过 Install Packages 对话框添加。我自己的习惯是编译 Dcl 包后重启一次 IDE,让 IDE 重新扫描包列表,这一步能避免一半的“没出现”问题。
4.2 现象:编译报内存错误或内部错误
Full Source 编译时踩到“内存错误”很常见,网上热词里也有一堆人在搜“Delphi 编译程序报内存错误”。特别是老项目用 Win32 平台编译、同时勾上了 Debug DCU 时,dcc32 经常中途崩溃。
原因是 IDE 的 Library 路径里有多个版本的 ODAC 源码和 DCU 文件混在一起,编译器加载了旧目标文件;少数情况下是启用了 64 位平台但运行时包没有匹配的 64 位版本。
解决分两步:先在 Tools > Options > Library 里把多余的 ODAC 路径清干净,只保留当前版本 Source 目录;然后在 Project Options 里把 Build with debug DCU 关掉,切回 32 位 Windows 平台重新编译。如果还报错,就在命令行手动执行 dcc32 -B 强制重建全部单元,这招杀掉了九成以上的诡异编译问题。剩余的极少情况是杀毒软件锁定了临时文件,把工程目录加白名单再试。
4.3 现象:Direct 模式连不上 Oracle 12c 及以上版本的数据库
这个坑非常典型:旧系统升级数据库到 12c 或 19c 后,原代码里用 SID 连接的方式突然不灵了。报错信息可能显示监听器拒绝连接,或服务名未知。
原因是 12c 以后多租户架构下,数据库实例名和可插拔数据库的服务名是两套体系。老代码里写 SID 指向实例名,但 listener 默认公布的是 PDB 的 SERVICE_NAME,两者对不上。ODAC 的 Direct 模式解析时用的是服务名,不是实例名。
解决方法是把连接串里的 SID 换成 SERVICE_NAME,并且确认大小写一致。比如原来写192.168.10.20:1521/ORCL不行,改成192.168.10.20:1521/orclpdb1就通了。排查时可以先用 sqlplus 在服务器上执行lsnrctl services看监听器注册了哪些服务名,照着填准没错。另外一个很容易被忽略的选项是 TOraSession.Options.Net 里的协议版本设置,默认值通常不用动,但如果你连接 19c 出现协议握手失败,找一下这个设置把它调到数据库支持的范围。
4.4 现象:32 位和 64 位 DLL 混用导致运行时报错
这种情况多发在从 32 位迁移到 64 位的过程里。老工程编译成 64 位后,直接拷贝原来的运行库部署,程序启动时报“无法定位程序输入点”或直接说缺少 DLL。
ODAC 的运行时 DLL 是区分位宽的,32 位版和 64 位版的 DLL 文件名可能完全一样,内部导入函数不同。如果你把 64 位的 exe 和 32 位的 DLL 放在一起,加载时就会炸。
解决方法是确认编译目标平台后,从对应位的运行时目录拷贝文件。我建议直接打开 Project Options 看当前目标平台,再回到 Source 下找对应位宽的编译输出目录,一整包拷过去。如果项目同时出 32 位和 64 位两个版本,部署目录必须分开,文件名相同也不要混用。这个坑排除了半天,最后其实就是 DLL 位宽的问题,说多了都是泪。
4.5 现象:改了 Full Source 源码,但运行效果没变化
Full Source 最大的吸引力就是可以改源码,但很多朋友改完发现行为没有任何变化,以为是自己改错地方了。其实大概率是 IDE 没重新编译包。
原因在于 Delphi 的 Library 搜索路径里同时有 Source 路径和 DCU 路径,编译器优先加载已存在的 .dcu 文件,你改的是 .pas,旧 .dcu 还在,编译器根本不读新源码。
解决方法是编译前先删掉对应目录下的 .dcu 和 .dcp 文件,再重新编译 run-time 包。命令行里加 -B 参数也是同样作用。我在日常开发里改完源码会执行一次全量 rebuild,并且确认 Library 路径里 Source 目录排在 DCU 目录之前。养成这个习惯后,再也没被“改了没用”这种假象骗过。
5. 让包里的源码持续生效:验证、迁移与后期维护
5.1 先做个最小测试程序验证连接字符串
换了一个新版本控件包后,我习惯先做一个最小测试程序,不写业务逻辑,只有一个按钮和一个 TOraSession,把直连、OCI 两种模式的连接都跑一遍。这看起来很基础,但真出问题时它能帮你快速二分定位:是控件装歪了,还是连接参数写错了。
测试程序里我会把连接结果写进 Memo 控件,包括 Sess.Connected 的值和最后一条错误信息。错误信息要保留原始文本,不要包装成“连接失败”这种没用的提示。ODAC 的错误前缀通常是 ORA-,后面跟数字和描述;还有一批 Devart 自己的错误号不带 ORA 前缀,对应它们的文档查。把最小测试程序留在工程目录里,后面的每次升级都先跑它,能节约大量排查时间。
5.2 上线换机:只拷贝运行时文件够不够
老项目换新机器上线时,经常有人问能不能只拷 exe 加几个 DLL。这问题要分模式回答。Direct 模式理论上可以只拷运行库,但我做过太多交付项目,实际现场往往缺这缺那。可靠做法是把运行库目录整个拷过去,别“精选”文件。OCI 模式就更不用说了,Oracle 客户端一套都不能少。
我的做法是在部署目录里加一个 version.txt,写明控件包版本号、编译平台位宽、数据库版本和连接模式。半年后现场出了问题,拿着这个文件就能判断是不是版本匹配问题。这个习惯救过我不少次,尤其当项目被转手维护后,新接手的人完全不知道当初用的哪套组合。
5.3 我常年保留的一个习惯:用版本号清单管理控件包
最后说个我自己的管理习惯:在本地建一个控件包清单文件,每次安装或升级 Devart.ODAC,就记录三样东西——Delphi 版本、ODAC 版本、编译方式是标准装还是手动编译。升级后如果出新问题,能直接回退到上一版,不用重新摸索安装步骤。
这个习惯是吃了大亏换来的。之前我把一个老项目的 ODAC 从 10.x 升到 12.x,Direct 模式某些 SQL 的取数行为有点变化,数据库负载也高了。当时没有任何记录,不知道怎么回退。后来我在每个工程目录都保留一份安装说明,把版本清单、连接串模板、编译命令全写进去。以后不管是自己维护还是移交别人,都不会再走一遍从头开始的弯路。
希望这篇笔记能帮你少踩几个我踩过的坑,把 ODAC 这套控件真正落地到你手头的 Delphi 工程里。
本文还有配套的精品资源,点击获取