# 数据导入 **本文引用的文件** - [IOManager.cpp](file://cpp/Managers/IOManager.cpp) - [IOManager.h](file://h/IOManager.h) - [Constant.h](file://h/Constant.h) - [DataOperator.h](file://h/DataOperator.h) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考量](#性能考量) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) ## 简介 本文件面向“数据导入”功能的完整流程进行深入文档化,重点覆盖: - CIOManager::Import 方法如何验证源.accdb文件的有效性(数据库版本检查、密码验证机制) - 导入过程中的事务管理与数据一致性保障 - ImportProjectToDB、ImportTzToDB 等系列方法如何解析外部数据库并安全导入到当前系统数据库 - 数据映射规则、主键处理、外键约束维护及冲突解决策略 - 导入失败时的回滚机制与错误报告方式 ## 项目结构 数据导入功能位于 Managers 层,核心类为 CIOManager,负责导入与导出的统一入口;导入流程围绕 Access 数据库(.accdb)展开,使用 ADO/ADOX 进行连接与表结构创建,并通过事务保证一致性。 ```mermaid graph TB subgraph "导入模块" CIO["CIOManager
导入/导出入口"] Imp["Import()
验证与事务控制"] Proj["ImportProjectToDB()"] Tz["ImportTzToDB()"] Spt["ImportSptToDB()"] Rsp["ImportRspTdToDB()"] Ipsp["ImportIpspTdToDB()"] end subgraph "系统数据库" SysConn["_ConnectionPtr
系统数据库连接"] Cat["ADOX::Catalog
表结构管理"] end subgraph "外部数据库(.accdb)" ExtConn["_ConnectionPtr
外部数据库连接"] DbVer["dbversion 表
版本校验"] end CIO --> Imp Imp --> Proj Imp --> Tz Imp --> Spt Imp --> Rsp Imp --> Ipsp Imp --> SysConn CIO --> Cat Imp --> ExtConn ExtConn --> DbVer ``` 图表来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) - [IOManager.h](file://h/IOManager.h#L15-L51) 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) - [IOManager.h](file://h/IOManager.h#L15-L51) ## 核心组件 - CIOManager:导入/导出的统一入口,提供 Import/Export 方法,内部封装对各业务表的导入逻辑。 - 外部数据库(.accdb):包含 project、tz、td、tdhead、parameter、rspcon、ipspcon、gr、scon、channel、script、dbversion 等表。 - 系统数据库:通过 ADOX 创建目标表结构,使用 ADO 执行插入与更新。 - 常量与返回码:统一的执行状态码(成功/失败/取消/重复/关联异常等),用于错误上报与流程控制。 章节来源 - [IOManager.h](file://h/IOManager.h#L15-L51) - [Constant.h](file://h/Constant.h#L138-L151) ## 架构总览 导入流程采用“打开外部数据库 -> 版本校验 -> 开启系统数据库事务 -> 分表导入 -> 提交或回滚”的模式。每个导入方法均以“先查询是否存在同名记录 -> 若不存在则插入 -> 存在则跳过(去重)”的策略避免重复导入;同时通过外键字段(如 PRID、TZID、PAID、SCID、DEID、TDID)将不同表之间的关系映射到系统数据库。 ```mermaid sequenceDiagram participant U as "用户" participant M as "CIOManager" participant E as "外部数据库(.accdb)" participant S as "系统数据库" participant T as "事务" U->>M : 调用 Import() M->>E : 打开外部数据库并设置密码 M->>E : 查询 dbversion 表进行版本校验 alt 校验失败 M-->>U : 返回取消/失败 else 校验成功 M->>S : BeginTrans() M->>S : 导入 project M->>S : 导入 tz M->>S : 导入 scon/channel/script M->>S : 导入 td/rspcon/ipspcon/gr alt 导入过程中发生异常 M->>S : RollbackTrans() M-->>U : 返回失败 else 成功 M->>S : CommitTrans() M-->>U : 返回成功 end end ``` 图表来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1960-L2064) ## 详细组件分析 ### CIOManager::Import 验证与事务控制 - 文件选择与连接 - 弹出文件对话框选择 .accdb 文件,构造连接字符串并设置数据库密码。 - 设置最大锁数属性以提升并发写入能力。 - 版本检查 - 通过查询外部数据库的 dbversion 表,要求存在特定键值(版本标识)才视为有效外部数据库。 - 若未命中或抛出异常,关闭连接并提示错误后返回取消/失败。 - 事务管理 - 成功通过版本检查后,开启系统数据库事务。 - 按顺序调用 ImportProjectToDB、ImportTzToDB、ImportSptToDB、ImportRspTdToDB、ImportIpspTdToDB。 - 成功则提交,失败则回滚并返回失败。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) ### ImportProjectToDB:工程表导入 - 映射字段 - 将外部 project 的 CN、PRname、PRdesc、location、PRdate、duration、PS、CS、PM、QAS、standard 映射到系统 project。 - 冲突处理 - 先按 CN 查询系统 project 是否已存在,若不存在则插入;存在则跳过。 - 主键/唯一性 - 以 CN 作为唯一键进行去重判断。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L2013-L2062) ### ImportTzToDB:测区表导入 - 映射字段 - 外部 tz 的 TZname、PRCN、TZdesc、location 映射到系统 tz。 - 关系解析 - 通过外部 tz.PRCN 查找系统 project 的 ID(PRID),再以 PRID+TZname 在系统 tz 中查重。 - 冲突处理 - 若系统 tz 中不存在相同 PRID+TZname,则插入;否则跳过。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1960-L2011) ### ImportSptToDB:脚本与通道导入 - 映射字段 - 外部 scon 的 CN、Sname、Eamount、CHamount、TPamount、definer、DEdate、SCdesc 映射到系统 scon。 - 外部 channel 的 CN、CHnumber、AR 映射到系统 channel(通过 SCID 关联 scon)。 - 外部 script2d 的 CN、CHnumber、TSN、C1、C2、P1、P2、K、N 映射到系统 script2d(通过 CHID 关联 channel)。 - 冲突处理 - scon:按 CN 去重;插入后获取新 ID(SCID)。 - channel:按 CN+CHnumber 去重;插入后获取新 ID(CHID)。 - script2d:按 CN+CHnumber+TSN 去重;插入时使用 CHID。 - 外键维护 - td 表导入完成后,根据外部 SCCN 更新 td.SCID 字段,完成脚本与测线的关联。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1385-L1519) ### ImportRspTdToDB:电阻率测线导入 - 映射字段 - 外部 td 的 TDname、DESN、PRCN、TZname、SCCN、TDtype、HFname、CFname、CFRamount、GRFname、GRFRamount 映射到系统 td。 - 外部 tdhead 的 TDname、DESN、Cdate、Ctime、rolling、RCamount、Rdirection、CRtime、CPE、CPN、weather、temperature、height、humidity、PM、OP、QA 映射到系统 tdhead。 - 外部 parameter 的 TDname、DESN 对应的 LCHamount、RCHamount、LCamount、RCamount、LEamount、REamount、Felectrode、Espacing、Clayout、CLfun 映射到系统 parameter。 - 外部 rspcon 的 TDname、DESN 对应的 A、B、M、N、K、SP、Ro、Vp、Ip、SD、RgA、RgB、RgM、RgN、Ttime 映射到系统 rspcon。 - 外部 gr 的 TDname、DESN 对应的 electrode、CableH、CableT、P1GR、P2GR 映射到系统 gr。 - 关系解析 - 通过 PRCN 获取 PRID,再通过 PRID+TZname 获取 TZID。 - 通过 DESN 获取 DEID(设备 ID),若不存在则置为 0。 - 通过 SCCN 获取 SCID,若不存在则置为 0。 - 插入 parameter 后获取 PAID;插入 td 后获取 TDID;随后插入 rspcon/gr 使用 TDID。 - 冲突处理 - td:按 TDname+DESN 去重;不存在则插入并生成 TDID。 - rspcon/gr:按 TDname+DESN+时间戳(或唯一组合)去重;不存在则插入。 - 外键维护 - 通过 PRID、TZID、PAID、SCID、DEID、TDID 维护层级关系。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1743-L1957) ### ImportIpspTdToDB:激电测线导入 - 映射字段 - 与电阻率测线类似,但映射到系统 rspcon 的字段为 SP、Ro、VP、IP、M1..M7、TH、D、Zp、FG、Am、Bm、Cm、Dm、r。 - 关系解析与冲突处理 - 同样基于 PRCN->PRID、PRID+TZname->TZID、DESN->DEID、SCCN->SCID、TDname+DESN->TDID 的映射链路。 - 以 TDname+DESN 去重插入 td;随后按 TDname+DESN+唯一字段去重插入 rspcon/gr。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1521-L1741) ### 数据映射规则与主键/外键处理 - 映射规则 - 外部表字段与系统表字段一一对应,部分日期/数值类型在插入前进行格式化或空值处理。 - 外部表中的“编号”字段(如 CN、PRCN、SCCN、DESN)作为跨表关联与去重的关键键。 - 主键处理 - 系统侧通过自增主键(如 scon.ID、channel.ID、script2d.ID、td.ID、parameter.ID)生成并维护。 - 外部侧以 CN、PRCN、SCCN、DESN 等作为唯一键进行去重。 - 外键约束维护 - 通过 PRCN->PRID、PRID+TZname->TZID、DESN->DEID、SCCN->SCID、TDname+DESN->TDID 等映射,确保 td、rspcon、gr、parameter 等表的外键字段正确指向父表。 - 冲突解决策略 - 优先采用“存在即跳过”的策略,避免重复导入导致的数据冗余与索引冲突。 - 对于脚本与测线的二次关联(如 td.SCID 的更新),在导入 scon 后统一执行,确保外键完整性。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1385-L1519) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1521-L1957) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L2013-L2062) ### 事务管理与一致性保障 - 事务边界 - 在 Import() 中开启系统数据库事务,随后依次导入各表;任一环节失败均触发回滚。 - 错误传播 - 导入过程中捕获 COM 错误并返回失败码;UI 层根据返回码进行提示与后续处理。 - 并发与锁 - 外部数据库连接设置最大锁数,减少锁竞争带来的写入阻塞。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) ### 导入失败的回滚与错误报告 - 回滚机制 - 导入任一阶段抛错,立即回滚系统数据库事务并关闭外部数据库连接。 - 错误报告 - 通过统一的状态码(成功/失败/取消/重复/关联异常等)向调用方反馈结果。 - UI 层根据状态码弹出提示或进入错误处理流程。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) - [Constant.h](file://h/Constant.h#L138-L151) ## 依赖关系分析 - CIOManager 依赖系统数据库连接与 ADOX Catalog,用于创建目标表结构与执行插入。 - 导入方法之间存在强依赖顺序:project -> tz -> scon/channel/script -> td/rspcon/ipspcon/gr。 - 外部数据库必须包含 dbversion 表且包含特定键值,否则导入被拒绝。 ```mermaid classDiagram class CIOManager { +Import() uint +Export() uint -ImportProjectToDB(pImp) -ImportTzToDB(pImp) -ImportSptToDB(pImp) -ImportRspTdToDB(pImp) -ImportIpspTdToDB(pImp) -m_pConnection -m_pCatalog } class Constant { +APP_SUCCESS +APP_FAIL +APP_CANCLE +APP_DUPLICATE +APP_RELATION +APP_OVERFLOW +APP_DEFAULT } CIOManager --> Constant : "使用返回码" ``` 图表来源 - [IOManager.h](file://h/IOManager.h#L15-L51) - [Constant.h](file://h/Constant.h#L138-L151) 章节来源 - [IOManager.h](file://h/IOManager.h#L15-L51) - [Constant.h](file://h/Constant.h#L138-L151) ## 性能考量 - 外部数据库写入优化 - 在导入前设置最大锁数,降低锁竞争,提高批量写入效率。 - 查询与去重策略 - 通过唯一键(CN、PRCN、SCCN、DESN、TDname+DESN 等)进行去重,避免重复插入。 - 事务粒度 - 将所有导入步骤置于同一事务内,减少中间态,保证一致性的同时也意味着单次失败需整体回滚。 - I/O 与网络 - .accdb 文件通常本地存储,性能瓶颈主要在数据库写入与索引构建;建议在导入前关闭不必要的 UI 刷新与日志输出。 [本节为通用性能建议,不直接分析具体文件] ## 故障排查指南 - 常见问题与定位 - 外部数据库无法打开或密码错误:检查连接字符串与密码设置;确认 .accdb 文件未损坏。 - 版本校验失败:确认外部数据库包含 dbversion 表且包含指定键值。 - 导入失败回滚:查看返回码与异常栈,定位具体导入方法;检查唯一键冲突与外键映射是否正确。 - 建议排查步骤 - 独立运行 ImportProjectToDB/ImportTzToDB,确认基础表导入成功。 - 检查 scon/channel/script 的关联是否正确,必要时手动执行 td.SCID 更新。 - 对照外部与系统表结构,核对字段映射与空值处理逻辑。 章节来源 - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1385-L1519) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1521-L1957) - [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1960-L2062) ## 结论 本导入流程通过严格的版本校验、事务控制与去重策略,实现了从外部 .accdb 到系统数据库的可靠迁移。其关键特性包括: - 明确的验证与错误处理路径 - 以唯一键驱动的去重与外键映射 - 事务边界内的原子性与一致性 - 清晰的失败回滚与状态码反馈 在实际部署中,建议结合业务场景对字段映射与去重策略进行微调,并在导入前做好备份与测试,以确保数据完整性与可追溯性。