14 KiB
AGENTS.md
项目定位
恒诺迁移工具是一个仅运行于 Windows 的 Oracle 数据库迁移桌面工具。当前维护目标是 henlo_migration_wpf10/:WPF + .NET 10,程序集名为“恒诺迁移工具”。工具从源库读取表结构、BOS 配置、存储过程/函数和表数据,将 SQL 保存为本地文本;经用户确认后,再把本地 SQL 执行到目标库。
本文是仓库级开发约定。分析、修改和验证默认都以当前 WPF 项目为准,除非任务明确点名旧项目。
目录边界
henlo_migration_wpf10/:当前唯一主程序,优先分析和修改。henlo_migration/:旧 .NET Framework 4.8 / WinForm 版本,已废弃;不要把旧版的窗体、AntdUI 或 AutoUpdater.NET 设计套到主程序。henlo_migration_core10/:未投入使用的 .NET Core 版本,默认不修改。hc_preview/:界面预览或辅助内容,不是主程序源码。产品部署/:部署相关资料或产物,只有发布任务才处理。VELOPACK_MIGRATION.md、VELOPACK操作手册.md:更新与发布背景资料;若与代码冲突,以当前代码和pack.bat为准。
Git 仓库
- 项目远程仓库:
https://gitea.momozhua.site/qiangayi/henlo_migration_wpf10.git - 当前根目录已经初始化为 Git 工作区,默认分支为
main,远程名为origin。 - 可以使用
git status、git diff和提交历史检查改动。不要使用git reset --hard、强制推送或其他会丢失本地/远程改动的命令。 - fetch、pull、commit、push 等会改变工作区、历史或远程状态的操作必须符合用户当前任务;上传远程仓库需要明确授权。
- Git 提交说明统一使用简洁中文,直接描述本次改动的关键点,避免冗长过程说明。
当前技术基线
- 项目文件:
henlo_migration_wpf10/henlo_migration_wpf10.csproj - 目标框架:
net10.0-windows - UI:WPF + HandyControl 3.5.1
- MVVM:手写
INotifyPropertyChanged/命令实现,引用 CommunityToolkit.Mvvm 8.3.2,但当前主 ViewModel 未使用其源生成器 - Oracle 访问:SqlSugar 5.1.4.157 + Oracle.ManagedDataAccess.Core 23.5.0
- 配置解析:ini-parser 2.5.2
- JSON:Newtonsoft.Json 13.0.3
- 自动更新:Velopack 0.0.1298
- 当前版本号:以
.csproj的<Version>为唯一事实来源,不在本文硬编码版本 - Nullable:项目设置为
<Nullable>disable</Nullable>,源码中仍存在?注解,因此构建有既有CS8632警告
主程序结构
启动与界面
App.xaml:应用资源、HandyControl 主题和MainViewModel资源注册;启动页是Views/HomeWindow.xaml。App.xaml.cs:Velopack 初始化、旧版current/config.ini更新迁移、后台/手动更新、更新前后config.ini、data/与pre/备份恢复、全局异常日志。Views/HomeWindow.xaml:单窗口主界面,包含六个迁移 Tab、连接状态、SQL 编辑区和批量操作。Views/HomeWindow.xaml.cs:只处理窗口关闭和手动检查更新等窗口事件。Views/ConnectionDialog.*:源库/目标库连接配置与测试。Views/ErrorDialog.*:错误详情展示和复制。Behaviors/ClickToCopyBehavior.cs、Converters/StatusColorConverter.cs:界面辅助行为与状态颜色转换。
状态与编排
ViewModels/MainViewModel.cs:主状态容器和命令编排;初始化六个TabServices,管理数据库连接、单行/批量读写、SQL 编辑与断点续写。Models/TableRowModel.cs:每个迁移对象的名称、所属 Tab、读写状态。Enums/:Tab、状态、工作类型和输出扩展名枚举。
业务与数据访问
Services/TabConfig.cs/ITabConfig.cs:将 Tab、索引文件、输出后缀和读取委托组合成配置。Services/TabServices.cs:索引列表加载/保存、单行读写、排序、删除和状态切换。Services/DbServices.cs:Oracle SQL 的提取与执行核心:GetTableSql:读取表 DDL、注释、主外键、唯一键和索引;GetTableField:按TABLE.COLUMN读取单个物理表字段,不查询 BOS 元数据;目标字段不存在时新增,已存在时跳过;GetTableBos:读取 BOS 配置;GetTableBosField:按TABLE.COLUMN读取单个 BOS 字段配置,生成目标物理字段补充 SQL,并包含关联限定值/引用元数据;GetPrcSql/GetAllPrc:读取存储过程或函数源码;GetTableData:生成表数据 INSERT SQL;ExecuteCreate:按\n/分隔 SQL,在目标库逐条执行并检查USER_ERRORS。
Common/SqlSugarHelper.cs:维护orig(源库)和dest(目标库)两个 SqlSugar 连接。Common/SysConfig.cs:读取和写入用户持久目录下的config.ini。Common/CommonHelper.cs:运行目录、Velopack 持久目录、config.ini、data/、data/from/、pre/路径及文本读写。
真实数据流
六个 Tab 的映射由 MainViewModel 构造函数定义:
| Tab | 索引文件 | 内容文件 | 源库读取方法 |
|---|---|---|---|
| 表配置 | data/from/table.txt |
data/{对象名}_creat.txt |
DbServices.GetTableSql |
| 表字段 | data/from/table_field.txt |
data/{表名}.{字段名}_table_field.txt |
DbServices.GetTableField |
| BOS 配置 | data/from/bos.txt |
data/{对象名}_bos.txt |
DbServices.GetTableBos |
| BOS 字段配置 | data/from/bos_field.txt |
data/{表名}.{字段名}_bos_field.txt |
DbServices.GetTableBosField |
| 存储过程 | data/from/prc.txt |
data/{对象名}_prc.txt |
DbServices.GetPrcSql |
| 表数据 | data/from/data.txt |
data/{对象名}_data.txt |
DbServices.GetTableData |
读取流程:索引项 -> 调用源库读取委托 -> 生成 SQL 文本 -> 保存到 data/ -> 更新读取状态并显示内容。
“表字段”位于“表配置”之后,列表项必须使用 TABLE.COLUMN。它只读取 Oracle 物理表字段定义和字段注释,不检查 AD_TABLE、AD_COLUMN 等 BOS 元数据。源物理表或字段不存在时读取失败;目标表不存在时写入失败;目标字段已存在时整项跳过,否则按源字段类型、默认值、可空性和注释新增。
读取 BOS 配置前会检查源库当前用户下的辅助过程。整表读取使用 HMIG_GET_TABLE_BOS_31,单字段读取使用 HMIG_GET_TABLE_BOS_FIELD_31;若过程不存在,程序从运行目录的同名 pre/*.prc 脚本安装,检查 USER_ERRORS 和对象状态后再读取。单字段列表项必须采用 TABLE.COLUMN 格式。界面不提供手动“预处理”入口。
单字段 SQL 写入目标库时,限定值组按名称、限定值按组和值判断,只补充缺失项;引用元数据按引用表名和字段 DBNAME 映射,目标引用字段不存在或不唯一时直接报错,不自动创建。
单字段读取还会查询源库 USER_TABLES、USER_TAB_COLUMNS。源对象是物理表且源字段存在时,输出文件首先检查目标库物理表和字段:目标表不存在时报错,目标字段不存在时按源字段的数据类型、长度、精度和字符语义执行 ALTER TABLE ... ADD。源对象是视图或 BOS 计算字段时不生成物理字段 DDL。
写入流程:索引项 -> 读取对应 data/*_{后缀}.txt -> DbServices.ExecuteCreate -> 在目标库执行 -> 更新写入状态。批量写入遇到第一条失败即停止,并在内存中记录断点;断点不会跨进程持久化。
删除列表项会同时删除对应内容文件。调整顺序会立即覆盖索引文件。新增对象名会被转为小写,数据库读取时再按需要转大写。
配置和运行时文件
config.ini保存源库和目标库的 IP/服务名、用户名、密码。当前实现是明文读写,首次运行缺失时创建空配置;发布包不得携带本机配置。Velopack 安装态/便携态必须写在与Update.exe同级的根目录,不能写回每次更新都会整体替换的current/;普通未打包运行时仍写程序目录。- 从旧版本首次更新时,
OnAfterUpdateFastCallback会在 Velopack 删除旧current/临时备份之前,将其中的config.ini迁移到根目录。不要移除该兼容逻辑,除非已确认所有在用旧版本完成迁移。 - 不要在日志、回答、补丁或测试输出中展示真实连接串和密码。
- 修改或发布时不要用样例配置覆盖用户现有
config.ini。 data/和pre/是用户可编辑、更新时需要保留的运行数据;不要无故清空、批量改名或删除。error.log是全局异常日志,execute_log.txt记录目标库执行的 SQL;两者都是运行时文件,排查时可能含敏感业务信息。bin/、obj/、publish/、releases/、.vs/是构建、IDE 或发布产物。不要手工修改其中的 DLL、EXE、PDB、NuGet 包或生成源码。*.csproj.Backup*.tmp、_build*、_make_pack.bat、_write_pack.ps1、_debug_encoding.ps1是历史/辅助文件;正常构建和发布不要以它们为权威入口。
开发约定
- 保持现有命名空间
henlo_migration和现有目录分层。 - UI 状态、命令和业务编排放在
MainViewModel;可绑定的属性变更必须触发OnPropertyChanged,命令可用性变化时同步触发RaiseCanExecuteChanged。 - XAML 负责布局、样式和绑定;code-behind 仅保留必须依赖 Window/控件事件的逻辑。
- 通用 Oracle 提取/执行逻辑放在
DbServices,不要在 View 或 ViewModel 中复制 SQL。 - 新增 Tab 能力时同时检查
TabsEnum、CodeExt、TabConfig、MainViewModel映射、XAML 绑定、索引文件复制规则和更新备份范围。 - 耗时数据库调用不得阻塞 UI 线程;沿用现有异步命令和
Task.Run边界,UI 更新通过 WPF Dispatcher 或正常 await 回到 UI 上下文。 - 保持 SQL 文件的 Oracle 分隔约定:
DbServices.SplitStatements依赖换行后的/(实际分隔符为\n/)。修改生成 SQL 时必须验证普通 DDL、PL/SQL 块和末尾分隔符。 - 数据库对象名和用户数据不能直接拼入任意 SQL。查询参数优先使用
SugarParameter;确需生成 DDL 时必须处理标识符和字符串转义。 - 不要静默吞掉新异常。UI 可展示友好提示,但排障信息应保留在错误对话框或日志中;修改现有空
catch时要评估用户体验。 - 不做与任务无关的大规模格式化、Nullable 改造、依赖升级或旧项目同步。
数据库安全边界
源库和目标库不是等价环境:
Get*方法通常查询源库;ExecuteCreate明确写目标库。- 首次读取整表或单字段 BOS 配置时可能在源库自动创建对应的
HMIG_GET_TABLE_BOS_31或HMIG_GET_TABLE_BOS_FIELD_31;这不是只读操作,源库账号需要相应的CREATE PROCEDURE权限。 - 连接按钮会把界面中的连接信息写回
config.ini,并重建同时包含源库和目标库的 SqlSugarScope。 - 界面的“断开”当前只更新连接状态,并未释放或关闭底层连接对象。
除非用户明确要求并确认数据库、对象和影响范围,否则不要连接真实数据库、触发 BOS 辅助过程安装、执行目标库写入、清理数据或测试破坏性 SQL。需要验证数据库写入逻辑时优先使用代码审查、可控测试库或事务化的最小复现。真实目标库写入前必须提醒备份并确认权限。
构建与验证
在仓库根目录运行:
dotnet restore .\henlo_migration_wpf10\henlo_migration_wpf10.csproj
dotnet build .\henlo_migration_wpf10\henlo_migration_wpf10.csproj -c Debug
仅在依赖已经恢复且不希望访问包源时可用:
dotnet build .\henlo_migration_wpf10\henlo_migration_wpf10.csproj -c Debug --no-restore
当前没有测试项目。最低验证要求:
- 所有 C#/XAML 修改至少执行一次主项目构建。
- 仅文档修改可不构建,但要重新读取文件检查 Markdown、路径和命令。
- XAML/绑定修改除构建外,应在 Windows 上启动应用,检查六个 Tab、连接弹窗、按钮可用性和错误弹窗;不要因此连接生产库。
- SQL 生成/拆分修改需用不含真实数据的代表性 SQL 验证表 DDL、注释、约束、PL/SQL 和 INSERT。
- 更新逻辑修改需分别考虑普通
dotnet run(非 Velopack 安装)和 Velopack 安装态。
既有 CS8632 警告不是本次修改自动引入的错误,但不得新增编译错误。若任务专门处理 Nullable,应统一决定启用 Nullable 还是移除注解,不要零散压制警告。
本地调试可运行:
dotnet run --project .\henlo_migration_wpf10\henlo_migration_wpf10.csproj
启动会读取或创建用户持久目录下的配置,并可能尝试初始化更新检查;不适合无界面的 CI 验证。
版本与发布
- 仓库根目录的
RELEASE.md是当前发版流程、产物、上传和自动更新风险的权威说明。凡任务涉及版本号、Release 构建、Velopack、打包、便携包、自动更新、服务器部署或上传,必须先完整读取RELEASE.md,再执行或给出结论。 - 正式版本的用户可见变更记录维护在仓库根目录
CHANGELOG.md,发版时必须新增对应版本条目。 - 版本号只修改
.csproj中的<Version>,必须单调递增;正式发布入口是henlo_migration_wpf10/pack.bat。 - 发布是显式任务。未经要求不要运行打包、删除发布目录、修改版本号或上传更新服务器;构建通过不等于打包或自动更新验证通过。
- 若代码、脚本和
RELEASE.md不一致,以实际代码和pack.bat为准,并在同一任务中同步修正文档。
完成任务时的交付说明
简要说明:修改了什么、影响哪一层、执行了哪些验证、构建是否有错误/警告、是否因缺少 Oracle 测试库或 Velopack 安装态而存在未验证项。不要声称已验证真实数据库迁移,除非确实在明确授权的测试环境完成。