简介:面向Delphi 13 FireMonkey(D13 FS)开发者的UniDAC 10.3.0完整源码包,提供Oracle、SQL Server、MySQL、PostgreSQL、SQLite等主流数据库的统一访问接口,解决跨数据库应用开发中的连接与数据操作难题,适合需要灵活切换数据库的中高级Delphi程序员,也可作为企业级数据访问层的二次开发基础。包内共938个文件,大小仅12.19MB,以557个pas源码文件为核心,配合77个inc、62个res、51个dfm及49个lfm界面布局文件,另有43个dpk与37个lpk安装包源码、少量dll/dylib/so等跨平台动态库,以及bat一键编译脚本,结构清晰便于按需裁剪。压缩包附带安装工具,解压即可在IDE组件面板中直接调用各数据库驱动,纯源码零DLL依赖的特性支持Windows 32/64位、macOS、Linux乃至iOS/Android平台编译部署。内置批量更新、参数化SQL、宏替换、事务自动恢复等企业级功能,能有效提高复杂数据交互场景下的性能与稳定性,单文件EXE安装器进一步简化了配置流程。已有271人下载学习,适合需要在多数据库场景下构建统一数据访问层的Delphi开发者与团队。
1. UniDAC 10.3.0 for D13 FS 完整源码版附带安装工具,解决的是什么问题
当你的 Delphi 项目要从 MySQL 切到 PostgreSQL,又要保留同一套数据访问代码时,UniDAC 10.3.0 for D13 FS 完整源码版附带安装工具是一个能让你少熬夜的选择。它围绕 TUniConnection 这套统一连接对象,把不同数据库的协议差异包在内部,还交出了源码,允许你改类型映射和 SQL 方言。附带安装工具意味着不用手动往 IDE 里塞路径,工具会识别 BDS 版本并完成包注册。这篇笔记按这个标题,把源码版和安装工具的使用路径说清楚。适合已经装好 Delphi、想用 UniDAC 快速接入多数据库的开发同学。
2. 源码版和安装版怎么选:为什么我建议安装工具先跑一遍
2.1 源码版的价值:能改能调,但编译依赖更敏感
很多开发者一看到“源码版”就觉得高深,实际上它只是把 UniDAC 的核心单元作为 .pas 文件提供。你可以在开发环境里直接看 UniConnection 如何解析连接字符串,也能在本地化字符串出错时去查它内部映射表。这个价值在你排查“为什么这个字段被转成了 string”这类问题时特别有用,比反编译干净得多。
但代价是编译依赖比安装版敏感。源码版不像安装版那样跑一下 exe 就能用,它期待你在安装工具或 IDE 里手动配置一个关键搜索路径:Source 目录。如果这一步没搭配好,打开包文件时就会遇到“unit not found”的报错。和 FireDAC 那种内置组件不同,UniDAC 源码版首次编译时需要先编译 DAC 核心,再编译各自数据库的 Provider。这个依赖顺序没有写进界面,装的时候容易忽略。
我个人的习惯是:先让安装工具替你把这个坑填掉。它会自动把 Source 路径写进 Delphi 的库搜索路径,并编译出可供 IDE 识别的 .bpl 包。之后再打开项目。这相当于给自己留了后悔药,哪怕你后续要手动重编译,也站在了一个干净基础上。
2.2 安装工具的三步自动化:BDS版本识别、路径注入、包注册
安装工具的本质,是代替你完成三件容易出错的事。第一是 BDS 版本识别。UniDAC 的 for D13 这个标识,在安装工具的界面里通常对应某个 RAD Studio 版本号。工具通过读注册表找到对应版本的安装根目录,并据此定位 .bpl 输出路径。这一步如果识别错,后面所有路径都会偏移到错误的版本目录下。
第二是路径注入。安装工具会把组件 Source 目录和 Include 目录追加到 Delphi 的 Library Path 中。这个路径一旦没写好,后续源码编译必然报找不到单元。我在 Win32 和 Win64 两套环境下分别验证过,如果工具只注入了一条路径,另一平台编译时就会全盘崩溃。
第三是包注册。工具会在 IDE 的设计期包列表里写入运行时包和设计期包的名称,让你打开 Delphi 后能在组件栏里直接看到 UniDAC 选项卡。手工做这步需要自己去 Project Manager 里 Add 包文件,容易漏。而且设计期包和运行期包的加载顺序也有讲究,装错顺序后 IDE 会启动报错。
2.3 解压后先核对目录:确定这个源码版不是一堆散文件
拿到标题这种“完整源码版附带安装工具”的包,我一般不会直接双击安装工具,而是先看解压结构。通常来说,这类包会包含 install 或 setup 目录,里面放安装工具;source 目录放 .pas;packages 目录放 .dpk 和 .dproj;docs 目录放文档。用表格记录一下:
| 目录/文件 | 作用 | 没有它会怎样 |
|---|---|---|
| install/ | 安装工具本体 | 需要全手动注册包,工作量大 |
| source/ | 组件源码 | 只能退到安装版,无法改源码 |
| packages/ | 包项目(.dpk/.dproj) | 无法生成运行时包,容易装不上 |
| docs/ | 版本说明和帮助文件 | 遇到驱动错误时无法快速查证 |
如果你解压后没有 packages 目录,只有零散 .pas,说明这个包还需要你自己建包项目。这种情况我建议直接放弃,因为它比标准源码版多一道手工活,后续升级维护成本太高。另外要注意路径里不要有空格和中文,UniDAC 的编译对路径空格不算友好,这是我踩过一次的教训。
2.4 安装工具跑完后,怎么确认没有装歪
跑完安装工具,先不要急着写代码。打开 Delphi,看组件面板里有没有“UniDAC”页签,页签下应该能看到 TUniConnection、TUniQuery、TUniTable、TUniScript 等图标。然后新建一个 VCL 项目,在窗体上拖一个 TUniConnection,双击属性面板里 ProviderName,打开下拉列表,如果能列出 MySQL、Oracle、PostgreSQL、SQLite 等名字,说明安装工具的 Provider 注册也成功了。
这一步的排查价值在于,很多安装不是完全失败的,而是只注册了运行时包,没注册设计期包。结果是运行期程序能编译,但设计器里没有组件,拖不出来。这种情况下重新运行安装工具,勾选设计期包安装即可。
安装工具通常会生成一个 install.log。如果你安装后组件页签存在,但运行程序时提示找不到模块,优先看这个日志的最后几十行,往往记录了哪个 .bpl 被 load 失败。注意,日志里如果出现 Access denied,多半是杀毒软件把安装目录下的 bpl 文件隔离了,这是我从同事机器上见过最多的翻车现场。
3. 在 D13 环境装 UniDAC 10.3.0:从解压到跑通最小连接
3.1 解压后的目录结构:先分清 bin、source 和 install
压缩包解压后,不要放在有空格的中文目录下,尤其不要丢到“C:\Program Files”这种路径。UniDAC 的源码编译有时会沿路径搜索包文件,空格会切碎路径参数,导致找不到 DPK 文件。我一般习惯解压到 D:\Components\UniDAC1030,目录干净也方便记录版本。
如果包内本身有 install 目录,先进入该目录。常见做法是里面有一个可执行文件,名字可能叫 install.exe 或 setup.exe,也可能是一个批处理。找后缀为 .exe 的那个即可。source 目录按功能再分,至少能看见 Uni、DACCore 两个子目录,前者是统一的连接框架,后者是 Devart 的底层数据库访问核心。
3.2 用安装工具注册组件:三步完成
第一步是选择合适的 IDE 版本。首次运行时,工具通常会让你选择 Delphi 版本,这里对应标题里的 D13 标识。如果界面下拉列表显示的不是你的版本,不要强选相邻版本,先取消,检查注册表里有没有对应 BDS x.0 的 Key。这个 Key 一般位于 HKEY_CURRENT_USER\Software\Embarcadero\BDS 下,如果缺失,IDE 会无法被发现。
第二步是选数据库驱动。UniDAC 支持 Oracle、SQL Server、MySQL、PostgreSQL、SQLite、MongoDB 等,这里按你项目实际需要勾选。需要注意的是 MySQL 和 MariaDB 在部分版本里共用同一个 Provider,但底层库文件不同,如果你连的是 MariaDB,最好同时勾上 MySQL Provider 以保证兼容。
第三步是安装。工具会执行路径注入和包注册。安装过程中不要切出去,等待它编译运行时包。如果编译进度条卡住超过几分钟,多半是杀毒软件拦截了批处理,去隔离区看被隔离文件。跑完后回到 Delphi,打开 Project Manager,右键把设计期包添加到项目中。这个操作在安装版里会自动完成,源码版安装工具有时会漏掉最后一步,所以建议手动再确认一次。
3.3 验证安装:在 Delphi 里看到 UniDAC 组件页
安装完成后,新建一个 VCL 工程,切换到组件面板,找 UniDAC 页。如果这页没有,检查设计期包是否安装。安装成功后,在窗体上放置一个 TUniConnection。选中它,在对象检查器里可以看到 ProviderName 属性,下拉列表包含所有已安装的 Provider。这个下拉列表是由 UniDAC 的设计期包生成,如果设计期包有问题,下拉列表是空的。
这一步很关键:它验证的不是某个 dll,而是设计期和运行期的完整链路。很多“组件拖不出来”的问题都出在这个环节。
3.4 最小连接示例:用 UniConnection 连一次 MySQL
下面这个例子是 Delphi 10.x 下最简单的连接代码。我通常把它放在一个按钮事件里,用来快速验证驱动和连接参数。
uses Uni, MySQLUniProvider; procedure TForm1.btnConnectClick(Sender: TObject); var Conn: TUniConnection; begin Conn := TUniConnection.Create(nil); try Conn.ProviderName := 'MySQL'; Conn.Server := '127.0.0.1'; Conn.Port := 3306; Conn.Database := 'test'; Conn.Username := 'root'; Conn.Password := 'your_password'; Conn.Connect; ShowMessage('Connected: ' + Conn.Connected.ToString); finally Conn.Free; end; end;代码说明:先创建 TUniConnection,然后通过 ProviderName 指定驱动,再逐项填写连接属性。这里没有用 ConnectionString,是为了让参数在代码里可维护。Port 属性在 MySQL 默认 3306,如果你的实例换了端口,必须显式设置,否则 UniDAC 会按默认值连接,报错后很难排查。
注意这里的 MySQLUniProvider 单元来自 source 目录,它会被安装工具加到搜索路径。如果编译时提示找不到这个单元,说明安装工具的路径注入没有生效,回到第 3.2 步检查 Library Path。
3.5 连接串与 Provider 的关系:最少配置其实只有三行
很多老代码喜欢把 ProviderName、Server 等写进 ConnectionString 里,例如:
Conn.ConnectionString := 'Provider Name=MySQL;Server=127.0.0.1;Database=test;User ID=root;Password=123456;';我建议大家不要照抄这种写法。首先 Provider Name 是带空格的,手写容易笔误;其次 Password 明文写在 ConnectionString 里,代码评审时会被要求整改;再者用属性赋值时,IDE 的代码提示会帮你检查字段名,写错马上能发现。
当你用 ProviderName 属性时,UniDAC 内部仍会把所有连接属性组装成一个内部连接串,只是这个转换对你是透明的。好处是当你从 MySQL 切到 PostgreSQL 时,只需要改 ProviderName 和 Server、Database,Port 等属性,业务代码不用动。这一点是 UniDAC 最值得用的原因。
如果必须用 ConnectionString,务必要以“Provider Name=xxx;”开头,且不要漏掉分号。我从网上见过很多示例,漏掉最后分号的不少,最终报错在驱动加载阶段,而不是连接阶段,非常容易误判为 dll 缺失。
4. 用源码重编译 UniDAC:三个必调的编译参数
4.1 为什么要重编译:安装工具能装,但定制时需要动手
安装工具自动装好的包是一个通用二进制,针对 D13 环境已经够用。但遇到以下场景,你还是得自己重编译:你想在源码里加日志;你需要支持一个官方安装包中未包含的自定义 Provider;或者你要把运行时包拆成更小粒度。源码版提供 .dpk 包项目,但直接编译经常会遇到依赖路径不对、输出目录冲突等问题。下面三个参数是我每次都要检查的。
4.2 编译顺序和最小 MSBuild 命令:先 runtime 再 design
UniDAC 源码版通常不止一个包项目。比如 unidac_runtime.dpk 负责核心连接和查询对象,mysqlprovider_runtime.dpk 和 pgprovider_runtime.dpk 等则负责具体数据库。正确顺序是先编译核心运行时,再编译各数据库 Provider 运行时,最后编译设计期包。如果顺序反了,设计期包会引用不存在的 DCU 文件,报错信息是“file not found”。
我用 MSBuild 编译时的最小命令形如:
msbuild unidac_runtime.dpk /t:Build /p:Config=Release /p:Platform=Win32这里 .dpk 实际上是 Delphi 包项目,MSBuild 能识别是因为 IDE 会为它生成对应的 .dproj。如果在命令行下编译,要注意 /p:Config 值必须和 IDE 里设定的配置名一致,D13 环境通常是 Release 或 Debug。平台参数不要只编译 Win32,后面部署到 64 位机器时你会发现缺 64 位运行时包。
4.3 参数一:包输出目录要预留 Win32 和 Win64 两个子目录
这是最简单也最容易出错的地方。很多初学者把输出目录直接设成 Bin,结果 32 位和 64 位 DCU 混在一起。当你从一个平台切换到另一个平台时,编译器用了旧的 DCU,表现是编译通过,运行时报“Invalid pointer”或“Access violation”。
我一般会在包项目里把输出路径写成 “...\Output\Win32\Release” 和 “...\Output\Win64\Release”,同时把 DCU 输出目录也设置为各自平台下。这样不同平台的包不会互相踩踏。设置时注意项目选项里的 Output directory 和 Unit output directory,前者对应 .bpl/.dll,后者对应 .dcu。如果你用的是 IDE,在 Project Options 里改即可。
4.4 参数二:条件定义和搜索路径,缺一个就丢 Provider
源码包的单元里会根据 IDE 版本做条件编译,比如判断是否启用某个 Provider。缺少版本宏时,编译出来的包可能不包含 MySQL Provider,连接时报“Could not load provider”。我一般会在项目选项的条件定义里加上对应宏,而不是改源码。因为你一旦升级 Delphi,宏冲突会同时出现在多个源文件里,很难维护。
搜索路径必须至少包含 source 目录和 source\DACCore 目录。如果编译时报“Unit not found: DAC.Helpers”,就是 DACCore 没在搜索路径里。注意,DACCore 目录在安装工具里可能会自动注入,但重编译时你往往会重新指定一个输出目录,这时搜索路径会相对变化,需要检查。
4.5 参数三:包后缀名与版本号,要跟 IDE 匹配
Delphi 的运行时包通常带版本号,例如 dacCore103.bpl。UniDAC 安装工具会按 IDE 版本自动编写包名。如果你重编译时改了包名或后缀,之前设计期包引用的旧文件名就会对不上,结果是 IDE 启动时报“Package ... is either not loaded or is not designable”。不要随意改动包的输出文件名。
如果必须改,也要同步改设计期包里的 requires 引用。这个引用在 .dpk 文件头部,类似 “requires dacCore103;”。从源码编译时,检查一下你的 .dpk 里引用的包名是否和实际编译出来的文件名一致,尤其是当你用了自定义后缀后,这一处很容易漏。
5. UniDAC 安装与连接避坑:5 个常见问题排查记录
5.1 现象:安装工具找不到 BDS 安装目录
现象是在安装工具版本选择界面里,你的 Delphi 版本显示为灰色,点击下一步后直接退出。原因往往是注册表中对应 BDS 键缺失,或是 IDE 没有以当前用户身份运行过。解决方法是先以管理员身份打开一次 Delphi,让 IDE 把用户态注册表补上,再重新运行安装工具。如果仍然找不到,检查 HKEY_CURRENT_USER\Software\Embarcadero\BDS 下的子键数量和版本号。
5.2 现象:源码编译报“Unit not found: DUnit”
现象是编译运行时包时提示找不到 DUnit 相关单元。原因是源码包的测试目录引用了 DUnit,但 DUnit 不在搜索路径里。解决方法是不要去掉引用,而是把 DUnit 所在目录加到搜索路径;如果手头没有 DUnit,可以直接在包项目里排除测试包,不影响运行时包的编译。这个报错常见于从源码包直接打开 .groupproj 的场景,而安装工具不会帮你处理 DUnit。
5.3 现象:运行时提示“Could not load OCI.dll”
现象是程序在其他机器上连接 Oracle 时弹窗提示找不到 OCI.dll,但开发机上一切正常。原因是 UniDAC 选择 OCI 直连方式,但目标机器的 Oracle Instant Client 没有加入 PATH。解决方式有两个:一是把 Instant Client 的目录追加到系统 PATH;二是在连接参数里指定 OCI 库的绝对路径,例如 RealDriver=database。第二个办法更适合绿色部署,但要注意不同版本 Oracle 客户端对 dll 命名不同。
5.4 现象:连接池不生效,查询被反复新建连接
现象是程序压力一上来,数据库端立刻出现大量 Sleeping 连接,每个连接 TIME_WAIT 很久。原因通常是连接池没被真正使能,或者释放连接时直接 Free 而没有 Close。UniDAC 的池由 Provider 控制,MySQL 下面需要显式设置 Pooling=True,并且设置 Pooling.MaxItems=20 这类参数。更重要的是,TUniConnection 在 Free 前必须调用 Close,否则它不会把物理连接归还给池,而是直接断开。这个坑我吃过两次,后来在释放统一走 Close 再 Free 就稳定了。
5.5 现象:64 位和 32 位包冲突
现象是 IDE 中组件正常,但用 64 位配置编译运行时报类型不匹配,或提示包是不同平台编译。原因是安装工具通常只装一个平台的运行时包,你又手动编译了另一个平台,两个平台的 .bpl 混在了输出目录。解决方法是严格按平台分输出目录,并检查项目搜索路径中是否混入了另一个平台的 DCU。在 D13 环境里,64 位和 32 位路径千万别合并,否则这种问题会随机复发。
6. 连接监控与资源释放:我常用的验证技巧
我在每次装完 UniDAC 并跑通最小连接后,不会急着写业务代码,而是先做一个连接监控的测试。这个测试能验证连接池、网络异常、资源释放三个关键点。
我用 TUniMonitor 组件来观察连接状态。TUniMonitor 不需要放到窗体上,可以在代码里动态创建,并挂在同一个 TUniConnection 上。它的 EventKind 属性可以只勾选 ekConnect 和 ekDisconnect,这样每次实际建连和断开都会被记录。
var Mon: TUniMonitor; begin Mon := TUniMonitor.Create(nil); try Mon.Connection := Conn; Mon.EventKind := [ekConnect, ekDisconnect]; Mon.OnSQLLog := procedure(const Msg: string) begin Memo1.Lines.Add(Msg); end; Conn.Connect; Conn.Disconnect; Conn.Connect; finally Mon.Free; end; end;这段代码里,如果连续两次 Connect 只触发一次 ekConnect,说明连接池生效了。如果第一次 Disconnect 后第二次 Connect 又触发了一次 ekConnect 和一次 ekDisconnect,说明连接没有被归还到池里,此时要回头检查 Pooling 配置和 Close/Free 顺序。这个习惯帮我抓过很多隐藏的资源泄漏。
另外,我坚持在 TUniConnection 的 BeforeDisconnect 事件里记录完整连接串中数据库名,方便线上日志定位。我有一次上线前忽略了 Close 直接 Free,导致连接池里的连接一直挂在 TIME_WAIT 状态,从那以后我都把 Close 和 Free 分开写,也希望这个细节能帮到你。
本文还有配套的精品资源,点击获取