NavisworksTransport/doc/bugfixes/数据库兼容性_剖面盒导出修复报告.md

5.1 KiB
Raw Blame History

数据库兼容性 / 剖面盒导出修复报告

修复目标

  1. 打开旧版本数据库时崩溃schema 不兼容)
  2. NWF 多文档剖面盒导出时,无命中子树泄露到导出文件
  3. 反复剖面盒导出后崩溃COM 跨线程访问)
  4. 导出后剖面盒被关闭,状态栏按钮不同步

问题一:数据库 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() 无异常保护
  • BatchQueueItemsALTER TABLE ADD COLUMN 用裸 try-catch 吞异常
  • PathPlanningManager.DatabaseInitialize()catchthrow; 导致同一错误双重日志

修复

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.ModelsRootItem,不在 visibleSet 中的直接加入 ItemsToHideSetHidden 会级联隐藏所有后代,无需递归。


问题三:反复剖面盒导出崩溃

现象

连续多次"设置剖面盒 → 导出"操作,前几次正常,后续某次崩溃(无 managed 异常日志)。

根因

LayerManagementViewModel 中有两处不必要的 await Task.Run()

  • GetObjectsAndHiddenItems() 被包在 Task.Run 中,在后台线程调用 Navisworks COM APIModel.HasGeometryBoundingBox() 等)
  • 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 新增 SafeCreateIndexEnsureColumnExistsInitializeDatabase 加 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 powershellpwsh(兼容环境)
AGENTS.md 补充编译/部署调用方式说明
src/Utils/SectionClipHelper.cs 新增 RestoreClipBox 公开方法

问题四:导出后剖面盒被关闭,状态栏按钮不同步

现象

导出剖面盒后Navisworks ExportToNwd 内部会关闭剖分功能,但状态栏两个剖面盒图标按钮仍保持激活状态。

根因

ExportToNwd 是 Navisworks 内部行为,绕过我们的 SetClipBoxState。ViewModel 的 IsClipBoxEnabled/IsSelectionClipBoxEnabled 未感知到变化。

修复

VisibilityHelper.ExecuteWithPrecomputedHiddenItems 导出前用 SectionClipHelper.IsClipBoxEnabled + TryGetCurrentClipBox 保存剖面盒状态,导出后检查并在被关闭时恢复。

SectionClipHelper 新增 RestoreClipBox(BoundingBox3D) 公开方法。