- 数据库:SafeCreateIndex/EnsureColumnExists 防御旧schema;去掉无用PRAGMA user_version;去掉重复throw;清理注释编号 - 剖面盒导出:修复NWF多Model无统一根节点时空白子树泄露(RootItem级隐藏) - 崩溃修复:去掉LayerManagementViewModel中两处Task.Run,消除COM跨线程STA违规 - 重构:SectionBoxExporter新增ExportSectionBoxFromActiveView统一业务入口;LayerManagementViewModel删ExportSectionBoxToNwdAsync;删死代码ExportToJson(Document)/ShowSaveFileDialog - deploy-plugin.bat: powershell→pwsh;AGENTS.md补充编译部署调用说明
87 lines
4.3 KiB
Markdown
87 lines
4.3 KiB
Markdown
# 数据库兼容性 / 剖面盒导出修复报告
|
||
|
||
## 修复目标
|
||
|
||
1. 打开旧版本数据库时崩溃(schema 不兼容)
|
||
2. NWF 多文档剖面盒导出时,无命中子树泄露到导出文件
|
||
3. 反复剖面盒导出后崩溃(COM 跨线程访问)
|
||
|
||
---
|
||
|
||
## 问题一:数据库 schema 不兼容导致启动崩溃
|
||
|
||
### 现象
|
||
打开带有旧版本 `.db` 文件的模型时,插件初始化报错:
|
||
```
|
||
SQL logic error: no such column: DetectionRecordId
|
||
```
|
||
|
||
### 根因
|
||
`CreateTables()` 使用 `CREATE TABLE IF NOT EXISTS` + `CREATE INDEX IF NOT EXISTS` 组合。旧数据库表已存在但 schema 是旧版(缺 `DetectionRecordId` 列),`CREATE TABLE IF NOT EXISTS` 静默跳过,紧随的 `CREATE INDEX ... ON ...(DetectionRecordId)` 直接炸。
|
||
|
||
同时 `PathDatabase.InitializeDatabase()` 还有以下问题:
|
||
- `PRAGMA user_version` 只写入、从未读取
|
||
- `CreateTables()` 无异常保护
|
||
- `BatchQueueItems` 的 `ALTER TABLE ADD COLUMN` 用裸 `try-catch` 吞异常
|
||
- `PathPlanningManager.DatabaseInitialize()` 的 `catch` 里 `throw;` 导致同一错误双重日志
|
||
|
||
### 修复
|
||
**PathDatabase.cs:**
|
||
- 新增 `SafeCreateIndex()` 方法:建索引前用 `PRAGMA table_info` 检查列是否存在,缺列记 warning 跳过,不崩
|
||
- 新增 `EnsureColumnExists()` 方法:用 `PRAGMA table_info` 检查列,缺了才 `ALTER TABLE ADD COLUMN`,不吞其他异常
|
||
- 删除无用的 `PRAGMA user_version` 写入
|
||
- `InitializeDatabase()` 内用 `try-catch` 包裹 `CreateTables()` + `EnsurePathRoutesTableExtended()`,失败时关闭连接
|
||
- 清理注释中重复/杂乱的编号
|
||
- `CollisionDetectionRecords` 建表处加外键依赖注释
|
||
|
||
**PathPlanningManager.cs:**
|
||
- 去掉 `catch` 后的 `throw;`,外层 `OnModelsCollectionChanged` 已有独立日志
|
||
|
||
---
|
||
|
||
## 问题二:NWF 多文档剖面盒导出时空白子树泄露
|
||
|
||
### 现象
|
||
NWF 文件引用多个 NWD(各为一个独立 `Model`),剖面盒只覆盖其中一个子树的元素,导出后其他平行子树仍然出现在 NWD 中。
|
||
|
||
### 根因
|
||
`SectionBoxExporter.CalculateHiddenItems()` 通过"兄弟节点算法"确定隐藏项:收集可见项(剖面盒内元素及其祖先)的父节点,隐藏同父节点下的不可见兄弟。当模型有多个平行 `RootItem`(来自不同 `Model`)时,完全空白的子树没有任何节点进入 `visibleSet`,其 `RootItem` 不会出现在 `uniqueParents` 中,整棵子树被遗漏。
|
||
|
||
### 修复
|
||
**SectionBoxExporter.GetObjectsAndHiddenItems():**
|
||
在 `CalculateHiddenItems()` 之后补一步——遍历所有 `document.Models` 的 `RootItem`,不在 `visibleSet` 中的直接加入 `ItemsToHide`。`SetHidden` 会级联隐藏所有后代,无需递归。
|
||
|
||
---
|
||
|
||
## 问题三:反复剖面盒导出崩溃
|
||
|
||
### 现象
|
||
连续多次"设置剖面盒 → 导出"操作,前几次正常,后续某次崩溃(无 managed 异常日志)。
|
||
|
||
### 根因
|
||
`LayerManagementViewModel` 中有两处不必要的 `await Task.Run()`:
|
||
- `GetObjectsAndHiddenItems()` 被包在 `Task.Run` 中,在后台线程调用 Navisworks COM API(`Model.HasGeometry`、`BoundingBox()` 等)
|
||
- `NwdExportHelper.ExportToNwdWithPrecomputedHiddenItems()` 同样被包在 `Task.Run` 中
|
||
|
||
Navisworks COM API 要求 STA 线程访问,跨线程调用在少量使用时不崩,多次使用后触发 STA 违规导致进程崩溃。
|
||
|
||
### 修复
|
||
**LayerManagementViewModel.cs:**
|
||
- 去掉 `GetObjectsAndHiddenItems` 外的 `await Task.Run()` 包装,直接在 UI 线程调用
|
||
- 去掉 `ExportToNwdWithPrecomputedHiddenItems` 外的 `await Task.Run()` 包装,该方法内部已有 `Dispatcher.Invoke`,无需外层再切换线程
|
||
|
||
---
|
||
|
||
## 涉及文件
|
||
|
||
| 文件 | 改动 |
|
||
|------|------|
|
||
| `src/Core/PathDatabase.cs` | 新增 `SafeCreateIndex`、`EnsureColumnExists`;`InitializeDatabase` 加 try-catch;删除 user_version;清理注释 |
|
||
| `src/Core/PathPlanningManager.cs` | 去掉 `DatabaseInitialize` catch 中的 re-throw |
|
||
| `src/Core/SectionBoxExporter.cs` | `GetObjectsAndHiddenItems` 补空白 RootItem 隐藏逻辑 |
|
||
| `src/Utils/NwdExportHelper.cs` | 调试日志(已清理) |
|
||
| `src/Utils/VisibilityHelper.cs` | 调试日志(已清理) |
|
||
| `src/UI/WPF/ViewModels/LayerManagementViewModel.cs` | 去掉两处 `Task.Run` |
|
||
| `deploy-plugin.bat` | `powershell` → `pwsh`(兼容环境) |
|
||
| `AGENTS.md` | 补充编译/部署调用方式说明 |
|