This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,393 @@
# 数据库模式
<cite>
**本文档引用的文件**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://Install/Geomative Studio/database_modify.xml)
- [Project.h](file://h/Project.h)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp)
- [TdRecord.cpp](file://cpp/ProblemZone/TdRecord.cpp)
- [GeoMative.rc](file://GeoMative.rc)
- [Resource.h](file://Resource.h)
</cite>
## 目录
1. [引言](#引言)
2. [核心实体表结构](#核心实体表结构)
3. [数据库关系与ER图](#数据库关系与er图)
4. [关键字段业务含义与验证规则](#关键字段业务含义与验证规则)
5. [数据库版本演进历史](#数据库版本演进历史)
6. [结论](#结论)
## 引言
本文档旨在全面描述Geomative Studio软件所使用的Access数据库的结构。基于`DB/数据库字段修改记录.txt`文件的详细记录,本文档将深入分析项目、设备、脚本、测量数据等核心实体的表结构,包括字段名称、数据类型、主键/外键约束、索引和默认值。文档将解释各表之间的关系(如一对多、多对多等)并提供实体关系图(ER图)进行可视化表示。此外,文档还将包含数据库版本的演进历史和字段变更记录,并说明不同版本间的兼容性处理策略。
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
## 核心实体表结构
本节详细描述数据库中核心实体的表结构。信息主要来源于`IOManager.cpp`文件中创建数据库表的代码,以及`Project.cpp``Device.cpp`等文件中查询数据的SQL语句。
### 项目 (Project) 表
`project`表存储了工程项目的元数据。
**表结构:**
| 字段名称 | 数据类型 | 是否可为空 | 说明 |
| :--- | :--- | :--- | :--- |
| `ID` | AutoNumber | 否 | 主键,自增ID |
| `CN` | 文本 (40) | 否 | 项目ID |
| `PRname` | 文本 (20) | 否 | 项目名称 |
| `PRdesc` | 文本 (50) | 是 | 备注 |
| `location` | 文本 (50) | 是 | 位置 |
| `PRdate` | 日期/时间 | 是 | 日期 |
| `duration` | 长整型 | 是 | 持续时间(天) |
| `PS` | 文本 (20) | 是 | 项目主管 |
| `CS` | 文本 (20) | 是 | 现场经理 |
| `PM` | 文本 (20) | 是 | 项目经理 |
| `QAS` | 文本 (20) | 是 | QA |
| `standard` | 文本 (20) | 是 | 标准 |
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L227-L237)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp#L30)
- [GeoMative.rc](file://GeoMative.rc#L3835-L3850)
### 设备 (Device) 表
`device`表存储了设备的硬件和配置信息。
**表结构:**
| 字段名称 | 数据类型 | 是否可为空 | 说明 |
| :--- | :--- | :--- | :--- |
| `ID` | AutoNumber | 否 | 主键,自增ID |
| `DEname` | 文本 (20) | 否 | 设备名称 |
| `modelNO` | 文本 (20) | 否 | 型号 |
| `SN` | 文本 (20) | 否 | 序列号 |
| `HWV` | 文本 (20) | 否 | 硬件版本 |
| `SWV` | 文本 (20) | 否 | 软件版本 |
| `Mdate` | 日期/时间 | 是 | 生产日期 |
| `Mbatch` | 文本 (20) | 是 | 批次号 |
| `GPS` | 文本 (50) | 是 | GPS信息(2017.9.18新增) |
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L366-L375)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L135)
### 脚本 (Script) 表
`scon`表(在代码中常被称为`script`)存储了测量任务的配置脚本。
**表结构:**
| 字段名称 | 数据类型 | 是否可为空 | 说明 |
| :--- | :--- | :--- | :--- |
| `ID` | AutoNumber | 否 | 主键,自增ID |
| `CN` | 文本 (40) | 否 | 脚本ID |
| `Sname` | 文本 (20) | 否 | 阵列名称 |
| `Eamount` | 整型 | 是 | 电极数量 |
| `CHamount` | 整型 | 是 | 通道数量 |
| `TPamount` | 整型 | 是 | 点数 |
| `definer` | 文本 (20) | 是 | 操作员 |
| `DEdate` | 日期/时间 | 是 | 创建日期 |
| `SCdesc` | 文本 (50) | 是 | 备注 |
| `Rect` | 文本 | 是 | 矩形大小(2015.6.12新增) |
| `RectLoc` | 文本 | 是 | 矩形位置(2015.6.12新增) |
| `PoleDistance` | 文本 | 是 | 电极间距(2015.6.12新增) |
| `PoleStep` | 文本 | 是 | 电极步长(2015.6.12新增) |
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L564-L586)
- [Script.cpp](file://cpp/ProblemZone/Script.cpp#L18)
### 测量数据 (Measurement Data) 表
`td`表是存储测量任务的核心表,它与多种具体测量数据表(如`td1dcon`, `td2dcon`, `td3dcon`)存在一对多关系。
**表结构:**
| 字段名称 | 数据类型 | 是否可为空 | 说明 |
| :--- | :--- | :--- | :--- |
| `ID` | AutoNumber | 否 | 主键,自增ID |
| `TDname` | 文本 (20) | 否 | 任务名称 |
| `Tlocation` | 文本 (50) | 是 | 测区位置 |
| `DESN` | 文本 (20) | 否 | 设备序列号 |
| `SCCN` | 文本 (40) | 否 | 脚本ID |
| `Sname` | 文本 (20) | 否 | 阵列名称 |
| `Stype` | 整型 | 是 | 阵列类型 |
| `Ttype` | 整型 | 是 | 测试方法 |
| `Tmode` | 整型 | 是 | 测试模式 |
| `Eamount` | 整型 | 是 | 电极数量 |
| `TPamount` | 整型 | 是 | 点数 |
| `CHamount` | 整型 | 是 | 通道数量 |
| `N` | 整型 | 是 | 堆叠次数 |
| `TRwave` | 整型 | 是 | 发射波形 |
| `TRfrequency` | 整型 | 是 | 发射频率 |
| `Ifrequency` | 整型 | 是 | 发射频率 |
| `SAfrequency` | 整型 | 是 | 采样频率 |
| `Clayout` | 整型 | 是 | 装置类型 |
| `Espace` | 文本 | 是 | 电极间距(2015.6.12由数字改为文本) |
| `Edistance` | 文本 | 是 | 电极距离(2015.6.12由数字改为文本) |
| `weather` | 整型 | 是 | 天气 |
| `WDIR` | 整型 | 是 | 风向 |
| `temperature` | 整型 | 是 | 温度 |
| `height` | 整型 | 是 | 高度 |
| `humidity` | 整型 | 是 | 湿度 |
| `Cdate` | 日期/时间 | 是 | 创建日期 |
| `Ctime` | 日期/时间 | 是 | 创建时间 |
| `Tdate` | 日期/时间 | 是 | 测试日期 |
| `Ttime` | 日期/时间 | 是 | 测试时间 |
| `Rdirection` | 整型 | 是 | 电阻率方向 |
| `CRtime` | 整型 | 是 | 堆叠时间 |
| `PM` | 文本 (10) | 是 | 项目经理 |
| `OP` | 文本 (10) | 是 | 操作员 |
| `QA` | 文本 (10) | 是 | QA |
| `rect` | 文本 | 是 | 矩形大小(2015.6.12新增) |
| `rect_loc` | 文本 | 是 | 矩形位置(2015.6.12新增) |
| `SkipCable` | 整型 | 是 | 跳过电缆(2017.9.18新增) |
| `IsAutoGenerate` | 整型 | 是 | 是否自动生成(2017.9.25新增) |
| `TZID` | 长整型 | 是 | 测区ID(外键) |
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L369-L397)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L438-L440)
### 测量数据详情表
`td1dcon`, `td2dcon`, `td3dcon`等表存储了具体的测量数据点,与`td`表通过`TCHID``TSN`关联。
**通用字段结构 (以td2dcon为例):**
| 字段名称 | 数据类型 | 是否可为空 | 说明 |
| :--- | :--- | :--- | :--- |
| `ID` | AutoNumber | 否 | 主键,自增ID |
| `TSN` | 整型 | 否 | 任务序列号 |
| `TCHID` | 长整型 | 否 | 通道ID |
| `V` | 单精度浮点型 | 是 | 电压 |
| `I` | 单精度浮点型 | 是 | 电流 |
| `R0` | 单精度浮点型 | 是 | 电阻 |
| `SP` | 单精度浮点型 | 是 | 自电 |
| `bUse` | 是/否 | 是 | 记录是否有效(2015.6.2新增) |
| `Vrawdata` | 备注 | 是 | 原始电压数据 |
| `Irawdata` | 备注 | 是 | 原始电流数据 |
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L410-L435)
- [TdRecord.cpp](file://cpp/ProblemZone/TdRecord.cpp#L55-L57)
## 数据库关系与ER图
根据对代码的分析,数据库中的核心实体存在以下关系:
* **项目 (Project)****测区 (Tz)** 之间存在一对多关系。一个项目可以包含多个测区。
* **测区 (Tz)****测量任务 (Td)** 之间存在一对多关系。一个测区可以包含多个测量任务。
* **设备 (Device)****测量任务 (Td)** 之间存在一对多关系。一台设备可以执行多个测量任务。
* **脚本 (Scon)****测量任务 (Td)** 之间存在一对多关系。一个脚本可以被多个测量任务使用。
* **测量任务 (Td)****测量数据详情 (Td1dcon, Td2dcon, Td3dcon)** 之间存在一对多关系。一个测量任务包含多个数据点。
```mermaid
erDiagram
PROJECT {
AutoNumber ID PK
string CN UK
string PRname
string PRdesc
string location
datetime PRdate
long duration
string PS
string CS
string PM
string QAS
string standard
}
DEVICE {
AutoNumber ID PK
string DEname
string modelNO
string SN UK
string HWV
string SWV
datetime Mdate
string Mbatch
string GPS
}
SCON {
AutoNumber ID PK
string CN UK
string Sname
int Eamount
int CHamount
int TPamount
string definer
datetime DEdate
string SCdesc
string Rect
string RectLoc
string PoleDistance
string PoleStep
}
TZ {
AutoNumber ID PK
string CN
string TZname
string location
datetime Cdate
datetime Ctime
long PROID FK
}
TD {
AutoNumber ID PK
string TDname
string Tlocation
string DESN FK
string SCCN FK
string Sname
int Stype
int Ttype
int Tmode
int Eamount
int TPamount
int CHamount
int N
int TRwave
int TRfrequency
int Ifrequency
int SAfrequency
int Clayout
string Espace
string Edistance
int weather
int WDIR
int temperature
int height
int humidity
datetime Cdate
datetime Ctime
datetime Tdate
datetime Ttime
int Rdirection
int CRtime
string PM
string OP
string QA
string rect
string rect_loc
int SkipCable
int IsAutoGenerate
long TZID FK
}
TD1DCON {
AutoNumber ID PK
int TSN
long TCHID
float V
float I
float R0
float SP
boolean bUse
memo Vrawdata
memo Irawdata
}
TD2DCON {
AutoNumber ID PK
int TSN
long TCHID
float V
float I
float R0
float SP
boolean bUse
memo Vrawdata
memo Irawdata
}
TD3DCON {
AutoNumber ID PK
int TSN
long TCHID
float V
float I
float R0
float SP
boolean bUse
memo Vrawdata
memo Irawdata
}
PROJECT ||--o{ TZ : "包含"
TZ ||--o{ TD : "包含"
DEVICE ||--o{ TD : "执行"
SCON ||--o{ TD : "使用"
TD ||--o{ TD1DCON : "包含"
TD ||--o{ TD2DCON : "包含"
TD ||--o{ TD3DCON : "包含"
```
**Diagram sources **
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 关键字段业务含义与验证规则
本节列举核心表中关键字段的业务含义和可能的数据验证规则。
### 项目 (Project) 表
* **`CN` (项目ID):** 项目的唯一标识符。业务规则要求其在系统内必须唯一。
* **`PRname` (项目名称):** 项目的名称,用于用户识别。不能为空。
* **`PRdate` (日期):** 项目创建的日期,用于时间排序和报告生成。
* **`PS`, `CS`, `PM`, `QAS` (人员):** 记录项目相关人员,用于责任追溯。
### 设备 (Device) 表
* **`SN` (序列号):** 设备的唯一硬件标识符。业务规则要求其在系统内必须唯一。
* **`Mdate` (生产日期):** 设备的生产日期,用于设备生命周期管理。
### 脚本 (Scon) 表
* **`CN` (脚本ID):** 脚本的唯一标识符。业务规则要求其在系统内必须唯一。
* **`Eamount` (电极数量):** 定义了测量阵列中使用的电极总数。必须为正整数。
* **`CHamount` (通道数量):** 定义了测量任务中使用的通道数量。必须为正整数。
### 测量任务 (Td) 表
* **`TDname` (任务名称):** 测量任务的名称,用于用户识别。不能为空。
* **`Ttype` (测试方法):** 一个整型代码,通过`cm`表(代码映射表)关联到具体的测试方法名称(如“电阻率”、“激电”等)。
* **`Clayout` (装置类型):** 一个整型代码,通过`cm`表关联到具体的装置名称(如“温纳”、“施伦贝谢”等)。
* **`Espace` / `Edistance` (电极间距/距离):** 存储为文本类型,可能包含单位信息(如"5m"),提供了更大的灵活性。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 数据库版本演进历史
根据`DB/数据库字段修改记录.txt`文件,数据库经历了多次重要的结构变更。以下是按时间顺序整理的版本演进历史:
| 日期 | 变更内容 | 变更类型 | 兼容性说明 |
| :--- | :--- | :--- | :--- |
| 2015年6月2日 | 在`td1dcon`, `td2dcon`, `td3dcon`表中增加`bUse`字段,用于标记记录是否有效。 | 新增字段 | 向后兼容。旧数据的`bUse`字段默认为`True`(有效)。 |
| 2015年6月12日 | 1. 在`Td`表中增加`rect``rect_loc`字段。<br>2. 将`Td`表的`Espace``Edistance`字段从数字类型改为文本类型。<br>3. 在`scon`表中增加`Rect`, `RectLoc`, `PoleDistance`, `PoleStep`字段,并删除旧的`X0\Y0\X1\Y1`字段。 | 新增字段<br>修改字段类型<br>新增/删除字段 | 向后兼容。旧数据的`rect``rect_loc`为空。`Espace``Edistance`的数值被转换为字符串。旧的坐标字段被废弃。 |
| 2016年12月2日 | 1. 在`ac`, `acds`, `td_spc_attr`表中新增10个时窗的信息。<br>2. 在`cm`表中加入发射频率为9(0.03125Hz)。 | 新增字段<br>新增数据 | 向后兼容。新时窗字段在旧数据中为空。 |
| 2017年9月12日 | 在`project`以及`tz`表中加入默认的工程和默认测区。 | 新增数据 | 向后兼容。不影响现有数据。 |
| 2017年9月18日 | 1. 在`device`表中增加`GPS`字段。<br>2. 在`desetting`表中增加`CableType`, `LowPowerAlarm`, `AutoStack`字段。<br>3. 将`gr`表中的`ECODE`属性从文本改成整型。<br>4. 在`td`表中增加`SkipCable`字段。<br>5. 将`td`表中的`DESN`属性从必填改为非必填。 | 新增字段<br>修改字段类型<br>修改字段约束 | 向后兼容。`GPS`等新字段在旧设备记录中为空。`ECODE`的文本值被转换为对应的整型代码。`DESN`字段可为空。 |
| 2017年9月23日 | 新增`task_timer`表。 | 新增表 | 向后兼容。该表用于新功能,不影响旧数据。 |
| 2017年9月25日 | 在`td`表中添加`IsAutoGenerate`字段。 | 新增字段 | 向后兼容。旧任务的该字段为`False`。 |
| 2017年9月26日 | 在`timer_task`表中增加`PLCID`字段。 | 新增字段 | 向后兼容。 |
| 2017年9月28日 | 将`td1d/2d/3ddcon`表中的`V,I,R0,SP`的字段属性都改为非必填字段。 | 修改字段约束 | 向后兼容。允许存储不完整的测量数据。 |
| 2019年7月4日 | `medium`表新增加强梯度装置。 | 新增数据 | 向后兼容。 |
| 2019年7月14日 | 1. `medium`表新增跨孔装置。<br>2. 新增`TTaskInfoCoordinetes`表,用于保存电极坐标信息。 | 新增数据<br>新增表 | 向后兼容。 |
| 2019年12月3日 | 新增`TPictureInfo``TPictureCode`表,用于存放图片和二维码信息。 | 新增表 | 向后兼容。 |
| 2019年12月11日 | 新增`TLoggingTaskInfo``TLoggingTaskContent`表,用于支持测井功能。 | 新增表 | 向后兼容。 |
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
## 结论
本文档基于对Geomative Studio项目代码和数据库变更记录的分析,全面描述了其Access数据库的模式。数据库设计围绕“项目-测区-任务-数据”的核心流程,通过清晰的表结构和关系来管理地质勘探数据。数据库经历了从2015年至今的持续演进,通过新增字段、修改类型和增加新表的方式,不断扩展功能以支持新的测量方法和设备特性。所有变更都遵循了向后兼容的原则,确保了旧版数据在新版软件中的可用性。`cm`表作为核心的代码映射表,为系统提供了良好的可配置性和多语言支持能力。
@@ -0,0 +1,193 @@
# 测量数据模型
<cite>
**本文档引用的文件**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://Install/Geomative Studio/database_modify.xml)
- [Release\DB\数据库字段修改记录.txt](file://Release/DB/数据库字段修改记录.txt)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TaskDataOper.h](file://h/TaskDataOper.h)
- [CLoggingDataOper.cpp](file://cpp/logging/CLoggingDataOper.cpp)
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h)
- [TdRecord.h](file://h/TdRecord.h)
</cite>
## 目录
1. [引言](#引言)
2. [核心数据表结构](#核心数据表结构)
3. [几何信息记录设计](#几何信息记录设计)
4. [字段类型变更原因](#字段类型变更原因)
5. [定时任务管理机制](#定时任务管理机制)
6. [测井与图像数据管理](#测井与图像数据管理)
7. [电极坐标同步机制](#电极坐标同步机制)
8. [结论](#结论)
## 引言
本文件详细描述了Geomative Studio软件的测量数据模型,重点阐述了Td表及其关联表(如gr、ac、cm等)的结构设计。文档涵盖了2015年6月12日引入的测试任务几何信息记录设计、2017年9月23日和26日的定时任务管理功能,以及后续新增的测井和图像数据管理表。通过分析数据库修改记录和相关代码实现,本文档为理解系统的数据存储和管理机制提供了全面的参考。
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [Release/DB/数据库字段修改记录.txt](file://Release/DB/数据库字段修改记录.txt)
## 核心数据表结构
测量数据模型的核心是Td表,它存储了所有测试任务的基本信息。该表与多个关联表共同构成了完整的数据结构体系。gr表用于存储测量数据,cm表存储了代码和标签的映射关系,而tdchannel表则记录了通道信息。这些表通过ID等字段相互关联,形成了一个完整的数据网络。
```mermaid
erDiagram
Td {
int ID PK
string TDname
string DESN
string Sname
int Stype
int Ttype
int Eamount
int TPamount
string Edistance
string rect
string rect_loc
datetime Cdate
datetime Tdate
}
gr {
int ID PK
int TDID FK
string Ecode
datetime Mdate
datetime Mtime
int OMvalue
int StatusCode
}
cm {
int ID PK
string Cname
int Cvalue
string Clabel
int Lang
}
tdchannel {
int ID PK
int TDID FK
int CHnumber
int AR
}
Td ||--o{ gr : "包含"
Td ||--o{ tdchannel : "包含"
cm }|--|| Td : "Stype映射"
cm }|--|| Td : "Ttype映射"
```
**Diagram sources **
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
## 几何信息记录设计
2015年6月12日,系统对Td表进行了重要更新,增加了rect和rect_loc字段来记录测试任务的几何信息。这一设计变更旨在更精确地描述测量任务的空间布局。rect字段以文本类型存储矩形的大小,而rect_loc字段则记录矩形的位置信息。同时,系统删除了原有的X0\Y0\X1\Y1字段,采用了更灵活的文本格式来存储几何信息。
```mermaid
erDiagram
Td {
string rect
string rect_loc
}
SCON {
string Rect
string RectLoc
float PoleDistance
float PoleStep
}
Td }|--|| SCON : "几何参数"
```
**Diagram sources **
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
## 字段类型变更原因
在2015年6月12日的更新中,系统将Td表的Espace和Edistance字段从数字类型改为文本类型。这一变更的主要原因是增加了对多种单位和格式的支持。通过使用文本类型,系统可以存储包含单位标识的值(如"10m"、"5ft"等),提高了数据的灵活性和可读性。此外,文本类型还支持存储复杂的距离描述,如范围值或特殊标记。
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
## 定时任务管理机制
2017年9月23日,系统新增了task_timer表用于管理定时任务。该表与PLCID字段(2017年9月26日添加)共同构成了定时任务管理的核心。task_timer表存储了定时任务的配置信息,包括执行时间、周期等。PLCID字段用于标识与任务关联的PLC设备,实现了任务与特定设备的绑定。这一机制使得系统能够自动化执行测量任务,并与外部设备进行协调。
```mermaid
erDiagram
task_timer {
int ID PK
datetime TaskTime
int Interval
string PLCID
int Status
}
Td {
int ID PK
bool IsAutoGenerate
}
task_timer }|--|| Td : "生成任务"
```
**Diagram sources **
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h)
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 测井与图像数据管理
系统在2019年12月新增了TPictureInfo和TLoggingTaskInfo等表,用于管理测井和图像数据。TPictureInfo表存储了图片信息,包括岩性图片的路径和描述。TLoggingTaskInfo表则用于存储新建的测井任务信息,供用户选择和执行。这些新增表扩展了系统的功能,使其能够支持更复杂的测井和数据可视化需求。
```mermaid
erDiagram
TPictureInfo {
int ID PK
int LanguageID
string LithologyName
string LithologyPicPath
string LithologyType
}
TLoggingTaskInfo {
int TaskID PK
string TaskName
string Location
byte LogType
float SamplingInterval
float InitDepth
float EndDepth
}
TLoggingTaskContent {
int TaskID PK, FK
int TestID PK
float Depth
string Data
}
TPictureInfo ||--o{ TLoggingTaskContent : "关联"
TLoggingTaskInfo ||--o{ TLoggingTaskContent : "包含"
```
**Diagram sources **
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [CLoggingDataOper.cpp](file://cpp/logging/CLoggingDataOper.cpp)
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [CLoggingDataOper.cpp](file://cpp/logging/CLoggingDataOper.cpp)
## 电极坐标同步机制
2019年7月14日,系统新增了TTaskInfoCoordinetes表,用于管理电极坐标信息。该表的主要作用是将本地的坐标信息下发给GD设备,或者保存云端的坐标数据。通过这一机制,系统实现了电极坐标的同步和共享,确保了测量数据的一致性和准确性。TTaskInfoCoordinetes表与任务ID关联,为每个测量任务提供了精确的电极位置信息。
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 结论
Geomative Studio的测量数据模型经过多次迭代和优化,形成了一个功能完整、结构合理的数据管理体系。从最初的Td表到后来的定时任务管理和测井数据管理,系统的数据模型不断扩展以满足新的需求。通过分析这些设计变更,我们可以看到系统在灵活性、可扩展性和实用性方面的持续改进。这些改进不仅提升了系统的功能,也为用户提供了更强大的数据管理能力。
@@ -0,0 +1,222 @@
# 脚本数据模型
<cite>
**本文档中引用的文件**
- [database_modify.xml](file://database_modify.xml)
- [config.ini](file://config.ini)
- [Script.h](file://h/Script.h)
- [Script2D.h](file://h/Script2D.h)
- [Script3D.h](file://h/Script3D.h)
- [ScriptCE.h](file://h/ScriptCE.h)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
本文档旨在全面阐述Geomative Studio中2D/3D/CE测量脚本的数据模型设计,重点分析`td2dcon``td3dcon``td1dcon`等表的结构设计,以及`bUse`字段在记录有效性管理中的设计意图与实现方式。同时,深入解析SCON表中`Rect``RectLoc``PoleDistance`等字段在跨孔测量中的作用,阐明脚本生成过程中的数据访问模式、约束条件及`SkipCable``IsAutoGenerate`等字段的业务逻辑。
## 项目结构
Geomative Studio项目采用典型的C++/MFC架构,其核心功能围绕地质测量脚本的生成、管理和执行。项目结构清晰地划分为`cpp`(源代码)、`h`(头文件)、`DB`(数据库相关)、`Install`(安装配置)等目录。脚本相关的数据模型和业务逻辑主要集中在`cpp/Managers``cpp/Operator`目录下的`TdManager.cpp``DataOperator.cpp`等文件中,而数据结构定义则位于`h`目录下的`Script*.h`系列头文件。
```mermaid
graph TB
subgraph "核心模块"
Script[脚本管理]
Data[数据操作]
Task[任务执行]
end
subgraph "数据层"
DB[(数据库)]
Config[配置文件]
end
Script --> Data
Data --> DB
Task --> Script
Task --> Data
Config --> Script
Config --> Task
```
**图示来源**
- [database_modify.xml](file://database_modify.xml)
- [config.ini](file://config.ini)
**本节来源**
- [database_modify.xml](file://database_modify.xml#L1-L25)
- [config.ini](file://config.ini#L1-L73)
## 核心组件
本系统的核心组件围绕测量脚本(Script)的生命周期管理展开。`CScript`基类定义了所有脚本的通用属性和接口,而`CScript2D``CScript3D``CScriptCE`等派生类则分别实现了二维、三维和电容耦合(CE)测量脚本的特定功能。`TdManager`类负责将脚本配置转化为具体的测量任务,并管理任务数据的生成与存储。`DataOperator`类则提供了对数据库中测量记录的直接操作能力,如启用/禁用特定记录。
**本节来源**
- [Script.h](file://h/Script.h#L1-L39)
- [Script2D.h](file://h/Script2D.h#L1-L32)
- [Script3D.h](file://h/Script3D.h#L1-L43)
- [ScriptCE.h](file://h/ScriptCE.h#L1-L28)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2981-L3000)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L3869)
## 架构概述
系统采用分层架构,上层为用户界面,中层为业务逻辑处理(Manager和Operator),底层为数据存储(数据库)。脚本数据模型是连接业务逻辑与数据存储的核心。当用户创建一个测量任务时,系统会根据选择的测量类型(2D/3D/CE)实例化相应的脚本类,生成具体的测量序列,并将这些序列作为记录插入到`td2dcon``td3dcon``td1dcon`等结果表中。`bUse`字段在此过程中起到关键的过滤作用,确保只有有效的测量序列被实际执行。
```mermaid
graph LR
UI[用户界面] --> BL[业务逻辑层]
BL --> DL[数据层]
subgraph 业务逻辑层
SptMng[脚本管理器]
TdMng[任务管理器]
DataOp[数据操作器]
end
subgraph 数据层
DB[(数据库)]
end
SptMng --> TdMng
TdMng --> DataOp
DataOp --> DB
TdMng --> DB
```
**图示来源**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2981-L3000)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L3869)
## 详细组件分析
### 脚本数据表结构分析
系统为不同类型的测量任务设计了专用的结果表,以存储测量配置和结果。这些表包括`td2dcon`(二维测量)、`td3dcon`(三维测量)和`td1dcon`(一维测量)。这些表的结构高度相似,均包含电极配置(如`C1`, `C2`, `P1`, `P2``a`, `b`, `x`, `y`)、几何因子`K`、测量值`V`, `I`、视电阻率`R0`以及关键的`bUse`字段。
#### bUse字段的设计意图与实现
`bUse`字段(类型为Yes/No)是标记记录有效性的核心机制。其设计意图在于提供一种灵活的“软删除”或“临时禁用”功能,允许用户在不删除原始数据的情况下,排除某些测量序列。例如,当某个电极被确认为故障时,可以批量更新所有涉及该电极的记录的`bUse`字段为`false`,从而在后续的数据处理和成图中忽略这些无效数据。
该字段的实现主要通过`DataOperator`类中的SQL更新语句完成。例如,在`DataOperator.cpp`中,存在多个`update td*con set bUse = false`的语句,用于根据电极编号或测点坐标批量禁用记录。这表明`bUse`字段是数据质量控制流程中的关键一环。
```mermaid
flowchart TD
Start([开始]) --> CheckElectrode["检查电极状态"]
CheckElectrode --> Faulty{"电极故障?"}
Faulty --> |是| UpdateDB["更新数据库: bUse = false"]
Faulty --> |否| KeepActive["保持 bUse = true"]
UpdateDB --> End([结束])
KeepActive --> End
```
**图示来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L3869)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L3978-L4205)
**本节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L4779)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L3978-L4205)
### SCON表字段在跨孔测量中的作用
虽然`database_modify.xml`中未直接定义SCON表,但从`TdManager.cpp`的SQL语句中可以推断出其存在及部分字段。`Clayout`(电缆布局)、`SkipCable`(跳过电缆)、`rect`(矩形区域)、`rect_loc`(矩形位置)等字段是配置跨孔测量的关键参数。
- **`rect``rect_loc`**: 这两个字段共同定义了跨孔测量的几何范围。`rect`可能表示矩形的尺寸(如长宽),而`rect_loc`则指定了该矩形在三维空间中的具体位置(如中心坐标或角点坐标)。它们为生成孔间测量的电极组合提供了空间约束。
- **`PoleDistance`**: 虽然在代码中未直接出现,但根据命名惯例,它很可能存储了电极之间的间距,这是计算几何因子`K`的基础。
- **`SkipCable`**: 此字段用于标记在测量过程中需要跳过的电缆。在复杂的多电缆系统中,某些电缆可能因损坏或维护而暂时不可用。`SkipCable`字段允许系统在生成测量序列时自动排除这些电缆上的电极,确保测量计划的可行性。
```mermaid
classDiagram
class SCON {
+int Clayout
+int SkipCable
+float CRTime
+float Edistance
+string rect
+string rect_loc
+int DESN
+datetime STime
+datetime ETime
}
class td2dcon {
+int TCHID
+int TSN
+int C1
+int C2
+int P1
+int P2
+int N
+float K
+float I
+float V
+float R0
+float SP
+bool bUse
}
SCON --> td2dcon : "生成"
```
**图示来源**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2981-L3000)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L337-L343)
**本节来源**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2891-L3000)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L181-L343)
## 依赖分析
系统的数据模型依赖于一个关系型数据库(从SQL语句推断,可能为Access或SQLite)。`td*con`系列表通过`TCHID`(通道ID)与`tdchannel`表关联,而`tdchannel`又通过`TDID`(任务ID)与更高层级的任务表关联,形成了清晰的层级依赖关系。此外,`Script*.h`头文件定义了数据结构,被`TdManager.cpp``DataOperator.cpp`等实现文件所依赖,体现了代码层面的依赖。
```mermaid
erDiagram
SCON ||--o{ td2dcon : "生成"
SCON ||--o{ td3dcon : "生成"
SCON ||--o{ td1dcon : "生成"
tdchannel ||--o{ td2dcon : "包含"
tdchannel ||--o{ td3dcon : "包含"
tdchannel ||--o{ td1dcon : "包含"
TASK ||--o{ tdchannel : "包含"
SCON {
int Clayout
int SkipCable
string rect
string rect_loc
}
td2dcon {
int TCHID PK, FK
int TSN PK
int C1
int C2
int P1
int P2
bool bUse
}
tdchannel {
int ID PK
int TDID FK
}
```
**图示来源**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L1299-L1496)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L3869)
**本节来源**
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L1299-L5796)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L4779)
## 性能考虑
脚本数据模型的设计对性能有重要影响。`bUse`字段的使用避免了物理删除大量记录,减少了I/O开销。然而,频繁地更新`bUse`字段(如批量禁用)可能会产生大量的数据库写操作。为优化性能,建议在应用层进行批量操作,减少数据库事务的提交次数。此外,`td*con`表上的`TCHID``TSN`字段应建立索引,以加速按通道和序列号的查询。
## 故障排除指南
当遇到测量数据异常时,应首先检查`bUse`字段的状态。如果预期的测量序列未被执行,可能是其`bUse`字段被错误地设置为`false`。可以通过查询`td*con`表中`bUse = false`的记录来定位问题。对于跨孔测量失败的情况,应检查`SCON`表中的`SkipCable``rect`/`rect_loc`配置是否正确,确保测量范围和电缆布局符合现场实际情况。
**本节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L3773-L4779)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L2891-L3000)
## 结论
Geomative Studio的脚本数据模型设计精巧,通过`td2dcon``td3dcon``td1dcon`等专用表实现了对不同类型测量任务的有效管理。`bUse`字段作为记录有效性的开关,为数据质量控制提供了极大的灵活性。`SCON`表中的`rect``rect_loc``SkipCable`等字段则是实现复杂跨孔测量配置的关键。理解这些数据结构和字段的业务逻辑,对于正确使用系统、分析测量数据以及进行故障排除至关重要。
@@ -0,0 +1,283 @@
# 设备数据模型
<cite>
**本文档引用的文件**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://database_modify.xml)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp)
- [Device.h](file://h/Device.h)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [设备数据模型结构](#设备数据模型结构)
3. [核心组件分析](#核心组件分析)
4. [数据流与业务规则](#数据流与业务规则)
5. [版本演进与兼容性](#版本演进与兼容性)
6. [结论](#结论)
## 引言
本文档旨在深入解析Geomative Studio软件中的设备数据模型,重点阐述device表的结构及其与desetting表的关系。文档将详细说明GPS字段的引入、CableType、LowPowerAlarm、AutoStack等配置字段的用途,解释设备参数配置的数据流和业务规则,包括设备状态监控和固件升级相关的数据存储逻辑。结合数据库变更记录,文档还将阐述设备数据模型的版本演进过程和兼容性处理策略。
## 设备数据模型结构
### 设备表(device)与配置表(desetting)关系
设备数据模型的核心是device表和desetting表。device表存储设备的基本信息,如设备名称、序列号、型号、硬件版本、软件版本等。desetting表则存储设备的配置参数,通过DEID字段与device表建立关联。这种分离设计使得设备基本信息和配置参数可以独立管理,提高了数据模型的灵活性和可维护性。
```mermaid
erDiagram
device {
uuid ID PK
string DEname
string SN UK
string modelNO
string HWV
string SWV
timestamp Mdate
string Mbatch
string GPS
}
desetting {
uuid ID PK
uuid DEID FK
int Ifrequency
int numformat
int Tsys
int Mvoltage
int Msys
int maxRG
int Tzone
int STdelay
int PSmode
int PBtone
int Ttone
int dimmer
int lang
string CableType
int LowPowerAlarm
int AutoStack
}
device ||--o{ desetting : "1对多"
```
**图表来源**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt#L23-L24)
- [Device.h](file://h/Device.h#L88-L103)
### 核心字段说明
- **GPS字段**:于2017年9月18日引入,用于记录设备的地理位置信息,支持野外作业的精确定位和数据关联。
- **CableType**:于2017年9月18日引入,用于标识设备连接的电缆类型,支持不同型号电缆的识别和管理。
- **LowPowerAlarm**:于2017年9月18日引入,用于设置低电量报警阈值,当设备电量低于设定值时触发报警,确保设备在关键作业中不会因电量不足而中断。
- **AutoStack**:于2017年9月18日引入,用于控制设备的自动叠加功能,提高数据采集的效率和一致性。
**章节来源**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt#L23-L24)
## 核心组件分析
### 设备管理类(CDevice
CDevice类是设备数据模型的核心实现,负责设备的全生命周期管理,包括设备信息的获取、参数配置、状态监控和固件升级等。该类通过m_pConnection成员变量与数据库连接,实现数据的持久化存储。
```mermaid
classDiagram
class CDevice {
+DWORD m_dwID
+UINT m_uState
+UINT m_uType
+BYTE m_ucDevType
+CSComPort m_sComPort
+CString m_szDevSN
+CString m_szDevName
+CString m_szModelNO
+CString m_szMDate
+CString m_szHWV
+CString m_szSWV
+CString m_szMBatch
+CString m_szMacAddress
+_ConnectionPtr m_pConnection
+FILE *m_pLogFile
+CDevice(DWORD dwID, _ConnectionPtr& pConnection)
+~CDevice()
+BOOL Reset()
+BOOL DelSynInfo()
+BOOL DelGRInfo()
+BOOL GetSynInfo()
+BOOL GetDevInfo()
+BOOL GetGRInfo()
+int GetPoleCount()
+BOOL Register()
+BOOL Unregister()
+BOOL SendFile(const CString &szHostFilePath, const CString &szLocFilePath, const CString& szLocFileName)
+BOOL ReceiveFile(const CString &szLocFilePath, const CString& szHostFileName,int nRetryCnt = 3)
+bool ShowFLDetailInfo(CListCtrl& devDetailList)
+bool ShowOLDetailInfo(CListCtrl& devDetailList)
+bool ShowGRInfo(CListCtrl& devGRList)
+bool ShowACInfo(CListCtrl& devDetailList)
+BOOL ModifyParameter()
+BOOL ShowCableHeadInfoDlg()
+BOOL IsTheNumofPoleChanged()
+BOOL TestGRForPerPole(int iSN, CStringArray& strResArray)
+BOOL TestGRForAllPole()
+void SetState(UINT uState)
+void SetID(DWORD dwID)
+void PrintLog(CString& strLog)
+int IsExistOtherUserData()
+int CheckGD10Password(CString strGD10Password)
}
```
**图表来源**
- [Device.h](file://h/Device.h#L33-L125)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L42-L71)
### 数据操作类(CDataOperator
CDataOperator类负责设备数据的读写操作,提供了一系列方法来初始化设备视图、显示设备信息、创建和删除项目等。该类通过m_pConnection成员变量与数据库连接,执行SQL查询和更新操作。
```mermaid
classDiagram
class CDataOperator {
+_ConnectionPtr m_pConnection
+CStateProcessor m_stateProcessor
+CHandleProcessor m_handleProcessor
+CDataOperator(_ConnectionPtr& pConnection)
+~CDataOperator()
+bool InitialNavDataView(CNavDataView* pNavDataView)
+void ShowProjectInfo(DWORD dwProHandle, CView *pAppDataView)
+void ShowTzInfo(DWORD dwTzHandle, CView *pAppDataView)
+void ShowRsp3DTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+void ShowRsp2DTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+void ShowRspCETdInfo(DWORD dwTdHandle, CView* pAppDataView)
+void LoadRspCERecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+void LoadRsp2dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+void LoadRsp3dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType)
+void ShowIps2DpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+void ShowIps3DpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+void ShowIpsCEpTdInfo(DWORD dwTdHandle, CView *pAppDataView)
+void LoadIpspCERecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType/* = 1*/)
+void LoadIpsp2dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType/* = 2*/)
+void LoadIpsp3dRecordbyPage(DWORD dwTdHandle, CView *pAppDataView, int iSType/* = 3*/)
+UINT CreateProjectInDB(CNavDataView* pNavDataView)
+DWORD GetTdIdFromNavDataView(CNavDataView *pNavDataView)
+void UpdateNavDataViewAfterDel(CNavDataView *pNavDataView)
+UINT DeleteProjectInDB(CNavDataView* pNavDataView)
}
```
**图表来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L69-L846)
### 设备操作类(CDevOperator
CDevOperator类负责设备的在线和离线操作,提供了一系列方法来初始化设备视图、显示设备信息、刷新接地电阻记录等。该类通过m_pConnection成员变量与数据库连接,执行SQL查询和更新操作。
```mermaid
classDiagram
class CDevOperator {
+_ConnectionPtr m_pConnection
+CStateProcessor m_stateProcessor
+CHandleProcessor m_handleProcessor
+HTREEITEM m_hOLRegDevRootItem
+HTREEITEM m_hOLNewDevRootItem
+HTREEITEM m_hFLDevRootItem
+CString m_strLocalFilePath
+CString m_strProCN
+CString m_strTzCN
+CDevOperator(_ConnectionPtr& pConnection)
+~CDevOperator()
+bool InitialNavDevView(CNavDevView* pNavDevView)
+void ShowFLDeviceInfo(DWORD dwDevHandle, CView *pAppFLDevView)
+void ShowOLDeviceInfo(DWORD dwDevHandle, CView *pAppOLDevView)
+void ExpandTree(CTreeCtrl* pTreeCtrl,HTREEITEM hItem)
+UINT DevieUpgrade(CNavDevView *pNavDevView)
+UINT ModifyDeviceParameter(CNavDevView *pNavDevView, CListCtrl &detailList)
+void ShowCableHeadDlg(CNavDevView *pNavDevView)
+UINT RefreshGRRec(CNavDevView *pNavDevView, CListCtrl &grList, int iItemIndex)
+UINT RefreshAllGRRec(CNavDevView *pNavDevView, CListCtrl &grList)
}
```
**图表来源**
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L39-L800)
## 数据流与业务规则
### 设备参数配置数据流
设备参数配置的数据流始于用户在图形界面中修改设备参数,通过CDevOperator类的ModifyDeviceParameter方法触发。该方法调用CDevice类的ModifyParameter方法,生成相应的配置命令并发送到设备。设备返回确认后,CDevice类将新的配置参数写入数据库的desetting表中。
```mermaid
sequenceDiagram
participant User as 用户
participant UI as 图形界面
participant DevOperator as CDevOperator
participant Device as CDevice
participant DB as 数据库
User->>UI : 修改设备参数
UI->>DevOperator : 调用ModifyDeviceParameter
DevOperator->>Device : 调用ModifyParameter
Device->>Device : 生成配置命令
Device->>Device : 发送命令到设备
Device->>Device : 接收设备确认
Device->>DB : 更新desetting表
DB-->>Device : 确认更新
Device-->>DevOperator : 返回结果
DevOperator-->>UI : 返回结果
UI-->>User : 显示结果
```
**图表来源**
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L435-L461)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L71-L72)
### 设备状态监控
设备状态监控通过CDevice类的ShowOLDetailInfo方法实现。该方法从数据库的device表和desetting表中读取设备的当前状态和配置参数,并在图形界面中显示。状态信息包括设备名称、型号、序列号、硬件版本、软件版本、制造日期、批次号以及各种配置参数的当前值。
**章节来源**
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L154-L278)
### 固件升级数据存储
固件升级过程由CDevOperator类的DevieUpgrade方法启动。该方法创建一个升级线程,调用CDevice类的ReceiveFile方法从服务器下载固件文件。升级完成后,新的固件版本信息被写入device表的SWV字段,确保版本信息的准确性和一致性。
**章节来源**
- [DevOperator.cpp](file://cpp/Operator/DevOperator.cpp#L384-L433)
- [Device.cpp](file://cpp/ProblemZone/Device.cpp#L682-L726)
## 版本演进与兼容性
### 数据库变更记录
设备数据模型的版本演进记录在`DB/数据库字段修改记录.txt`文件中。关键变更包括:
- **2017年9月18日**:在device表中增加GPS字段,在desetting表中增加CableType、LowPowerAlarm、AutoStack字段。
- **2017年9月25日**:在td表中添加IsAutoGenerate字段。
- **2019年7月4日**medium表新增加强梯度装置。
- **2019年7月14日**medium表新增跨孔装置,新增TTaskInfoCoordinetes表。
这些变更记录为数据模型的维护和升级提供了重要的历史参考。
**章节来源**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt#L1-L61)
### 兼容性处理策略
系统通过`database_modify.xml`文件和CUpdateDataBase类实现数据库的兼容性处理。CUpdateDataBase类在启动时解析`database_modify.xml`文件,根据当前版本和目标版本的差异,自动执行数据库结构的升级操作。升级操作包括增加表、删除表、修改表结构等,确保不同版本之间的数据兼容性。
```mermaid
flowchart TD
Start([系统启动]) --> CheckVersion["检查当前数据库版本"]
CheckVersion --> VersionMatch{"版本匹配?"}
VersionMatch --> |是| End([系统正常运行])
VersionMatch --> |否| ParseXML["解析database_modify.xml"]
ParseXML --> FindUpdate["查找版本更新记录"]
FindUpdate --> ExecuteUpdate["执行数据库更新"]
ExecuteUpdate --> UpdateTable["更新表结构"]
UpdateTable --> UpdateIndex["更新索引"]
UpdateIndex --> UpdateForeignKey["更新外键约束"]
UpdateForeignKey --> WriteVersion["写入新版本号"]
WriteVersion --> End
```
**图表来源**
- [database_modify.xml](file://database_modify.xml#L1-L25)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp#L20-L874)
## 结论
Geomative Studio的设备数据模型设计合理,通过device表和desetting表的分离实现了设备信息和配置参数的独立管理。GPS、CableType、LowPowerAlarm、AutoStack等字段的引入,增强了设备的功能性和智能化水平。系统通过CDevice、CDataOperator、CDevOperator等核心类实现了设备的全生命周期管理,确保了数据的一致性和可靠性。数据库变更记录和兼容性处理策略为系统的长期维护和升级提供了有力支持。
@@ -0,0 +1,208 @@
# 项目数据模型
<cite>
**本文档引用的文件**
- [Project.h](file://h/Project.h)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [ProManager.h](file://h/ProManager.h)
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://Install/Geomative Studio/database_modify.xml)
</cite>
## 目录
1. [项目表结构](#项目表结构)
2. [项目与测区关系](#项目与测区关系)
3. [默认工程与默认测区实现机制](#默认工程与默认测区实现机制)
4. [数据库字段演进历史](#数据库字段演进历史)
5. [关键字段业务含义](#关键字段业务含义)
6. [数据验证规则与访问模式](#数据验证规则与访问模式)
## 项目表结构
项目表(project)是系统中用于存储工程基本信息的核心数据表。根据代码分析,该表包含以下字段:
| 字段名称 | 数据类型 | 约束 | 默认值 | 说明 |
|---------|--------|------|--------|------|
| ID | AutoNumber | 主键 | 自增 | 项目唯一标识 |
| CN | Text | 唯一 | 无 | 项目编码(GUID) |
| PRname | Text | 非空 | 无 | 项目名称 |
| PRdesc | Text | 可为空 | 无 | 项目描述 |
| location | Text | 可为空 | 无 | 项目位置 |
| PRdate | Date/Time | 非空 | 当前日期 | 创建日期 |
| duration | Text | 可为空 | 无 | 项目周期 |
| PS | Text | 可为空 | 无 | 项目负责人 |
| CS | Text | 可为空 | 无 | 客户名称 |
| PM | Text | 可为空 | 无 | 项目经理 |
| QAS | Text | 可为空 | 无 | 质量保证标准 |
| standard | Text | 可为空 | 无 | 技术标准 |
**Section sources**
- [Project.h](file://h/Project.h#L26-L37)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp#L30-L45)
## 项目与测区关系
项目与测区之间存在一对多的关联关系。一个项目可以包含多个测区,但每个测区只能属于一个项目。这种关系通过外键 `PRID``tz` 表中实现。
在数据访问层,`CProManager::ShowTzList` 方法通过 `PRID` 字段查询指定项目下的所有测区,并在UI中展示。`CProManager::GetDMS` 方法根据句柄类型动态创建 `CProject``CTestingZone` 对象,实现项目与测区的统一管理。
```mermaid
erDiagram
project {
AutoNumber ID PK
Text CN UK
Text PRname
Text PRdesc
Text location
Date/Time PRdate
Text duration
Text PS
Text CS
Text PM
Text QAS
Text standard
}
tz {
AutoNumber ID PK
Number PRID FK
Text CN
Text TZname
Number TZtype
Date/Time Cdate
Text TZdesc
Text location
}
project ||--o{ tz : "包含"
```
**Diagram sources**
- [Project.h](file://h/Project.h#L26-L37)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L72-L73)
- [ProManager.h](file://h/ProManager.h#L13)
## 默认工程与默认测区实现机制
系统在创建新项目时会自动创建一个默认测区。该机制通过 `CProManager::CreateProjectInDB` 方法调用 `InsertDefaultTzToProject` 实现。
默认测区的特征如下:
- `TZtype` 值为 3,表示默认测区
- 名称为 "DefaultTestZone"
- 描述和位置均为 "None"
- 创建日期为 "1970-01-01"
在创建项目后,系统首先删除该工程下已存在的默认测区(防止重复),然后插入新的默认测区记录。此过程确保每个项目下仅存在一个默认测区。
```mermaid
flowchart TD
Start([创建项目]) --> CreateProject["执行CreateProjectInDB"]
CreateProject --> CheckExist["检查项目名称是否已存在"]
CheckExist --> |已存在| ShowError["显示错误信息"]
CheckExist --> |不存在| InsertProject["插入项目记录"]
InsertProject --> GetProjectID["获取项目ID"]
GetProjectID --> DeleteDefault["删除现有默认测区"]
DeleteDefault --> InsertDefault["插入默认测区"]
InsertDefault --> End([完成])
```
**Diagram sources**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L319-L340)
- [ProManager.h](file://h/ProManager.h#L59)
## 数据库字段演进历史
根据《数据库字段修改记录.txt》文件,项目相关表的演进历史如下:
| 日期 | 变更内容 | 说明 |
|------|---------|------|
| 2015-06-02 | 在 td1dcon、td2dcon、td3dcon 表中增加 bUse 字段 | 用于标记记录是否有效 |
| 2015-06-12 | 在 Td 表中增加 rect、rect_loc 字段,修改 Espace、Edistance 类型 | 支持测试任务的矩形区域记录 |
| **2017-09-12** | **在 project 和 tz 表中加入默认的工程和默认测区** | **核心变更:实现项目初始化机制** |
| 2017-09-18 | 在 device 表中增加 GPS 字段 | 增强设备定位功能 |
| 2017-09-25 | 在 td 表中添加 IsAutoGenerate 字段 | 标识任务是否自动生成 |
2017年9月12日的变更是项目数据模型的重要里程碑,它引入了默认工程和默认测区的概念,简化了项目创建流程,确保了新项目具有基本的结构完整性。
**Section sources**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt#L19-L21)
- [Release/DB/数据库字段修改记录.txt](file://Release/DB/数据库字段修改记录.txt#L19-L21)
## 关键字段业务含义
### 项目名称 (PRname)
- **业务含义**:项目的可读名称,用于用户识别
- **约束**:必须唯一,不能为空
- **验证规则**:创建时检查是否已存在同名项目
### 创建时间 (PRdate)
- **业务含义**:项目创建的日期
- **格式**YYYY-MM-DD
- **默认值**:系统当前日期
### 坐标系统 (CS)
- **业务含义**:项目使用的坐标参考系统
- **示例值**WGS84、CGCS2000
- **用途**:确保测量数据的空间参考一致性
### 项目编码 (CN)
- **业务含义**:项目的唯一标识编码
- **生成方式**:使用 GUID 生成器创建
- **特点**:全局唯一,用于跨系统数据同步
### 测区类型 (TZtype)
- **业务含义**:测区的分类标识
- **关键值**
- 3:默认测区
- 其他值:具体测区类型
- **验证**:创建默认测区时严格校验类型值
**Section sources**
- [Project.h](file://h/Project.h#L27-L37)
- [Project.cpp](file://cpp/ProblemZone/Project.cpp#L36-L45)
## 数据验证规则与访问模式
### 数据验证规则
1. **项目名称唯一性验证**:在 `CreateProjectInDB` 中通过查询 `project` 表检查名称冲突
2. **默认测区类型验证**:在 `CreateDefaultTzInDev` 中校验 `TZtype` 必须为 3
3. **必填字段验证**`PRname``PRdate` 等字段在数据库层面设置为非空
4. **日期格式验证**:使用 `Format(PRdate,'YYYY-MM-DD')` 确保日期格式统一
### 访问模式
系统采用句柄(Handle)机制管理项目和测区对象:
- 使用 `m_handleProcessor.GenerateHandle` 生成唯一句柄
- 通过 `GetDMS` 方法根据句柄获取对应的 `CProject``CTestingZone` 对象
- 对象缓存在 `m_dmsLinkList` 链表中,提高访问效率
数据访问遵循以下模式:
1. 通过句柄获取对象
2. 执行业务逻辑
3. 操作结果持久化到数据库
4. 更新缓存状态
```mermaid
sequenceDiagram
participant UI as 用户界面
participant PM as CProManager
participant DB as 数据库
participant Cache as 对象缓存
UI->>PM : 请求显示项目列表
PM->>DB : 查询dptt表获取项目ID
DB-->>PM : 返回项目ID列表
loop 每个项目ID
PM->>DB : 查询project表获取详细信息
DB-->>PM : 返回项目数据
PM->>Cache : 检查对象是否已缓存
alt 对象存在
Cache-->>PM : 返回缓存对象
else 对象不存在
PM->>PM : 创建CProject对象
PM->>Cache : 添加到缓存
end
PM->>UI : 返回项目信息
end
```
**Diagram sources**
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp#L248-L247)
- [ProManager.h](file://h/ProManager.h#L57)
@@ -0,0 +1,591 @@
# 数据库设计
<cite>
**本文档引用的文件**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://database_modify.xml)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DataOperator.h](file://h/DataOperator.h)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [UpdateDataBase.h](file://h/UpdateDataBase.h)
- [Project.h](file://h/Project.h)
- [Device.h](file://h/Device.h)
- [TestingData.h](file://h/TestingData.h)
- [TdRecord.h](file://h/TdRecord.h)
- [Script.h](file://h/Script.h)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
</cite>
## 目录
1. [引言](#引言)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 引言
本文档详细说明了Geomative Studio软件系统所使用的Access数据库的表结构、字段定义、数据类型和约束条件。文档基于数据库字段修改记录文件,描述了主要实体(项目、设备、脚本、测量数据)之间的关系和关联方式。同时,文档解释了数据访问模式和持久化机制,包括通过ADO进行数据库操作的实现细节。提供了数据库ER图、关键查询示例和性能优化建议,并说明了数据版本控制和迁移策略。
## 项目结构
Geomative Studio项目的数据库相关文件主要位于DB目录下,包括数据库文件和字段修改记录。系统使用Access数据库(.accdb格式)存储项目、设备、脚本和测量数据等信息。数据库操作通过ADOActiveX Data Objects)技术实现,代码中包含了完整的数据库连接、查询、更新和版本管理机制。
```mermaid
erDiagram
PROJECT {
long ID PK
string PRname
string CN
string CDate
string CTime
string Location
string Duration
string PS
string CS
string PM
string QAS
string Standard
}
DEVICE {
long ID PK
string DEname
string SN
string ModelNO
string MDate
string HWV
string SWV
string MBatch
string MacAddress
string GPS
}
TD {
long ID PK
long TZID FK
string TDname
string TLocation
string TDate
string TTime
int Ttype
int Stype
int EAmount
int TPAmount
int CHAmount
int N
int TRWave
int TRFrequency
int IFrequency
int SAFrequency
int CLayout
string ESpace
string Edistance
string rect
string rect_loc
int SkipCable
bool IsAutoGenerate
}
TZ {
long ID PK
long PRID FK
string TZname
string CN
string Location
string Duration
string PS
string CS
string PM
string QAS
string Standard
}
SCRIPT {
long ID PK
long TDID FK
int EAmount
int SType
int AR
string Rect
string RectLoc
string PoleDistance
string PoleStep
}
TdRecord {
long ID PK
long TdID FK
int Tsn
int N
float K
float I
float V
float R0
float SP
string Datetime
}
TASK_TIMER {
long ID PK
long TDID FK
string TaskTime
int PLCID
}
TTaskInfoCoordinetes {
long ID PK
long TDID FK
string ElectrodeCoordinates
}
TPictureInfo {
long ID PK
long TDID FK
string PicturePath
string Description
}
TPictureCode {
long ID PK
long TDID FK
string QRCodeData
}
TLoggingTaskInfo {
long ID PK
long PRID FK
string TaskName
string TaskDate
}
TLoggingTaskContent {
long ID PK
long TaskID FK
string PointData
string MeasurementValue
}
PROJECT ||--o{ TZ : "包含"
TZ ||--o{ TD : "包含"
TD ||--o{ SCRIPT : "关联"
TD ||--o{ TdRecord : "包含"
TD ||--o{ TASK_TIMER : "包含"
TD ||--o{ TTaskInfoCoordinetes : "包含"
TD ||--o{ TPictureInfo : "包含"
TD ||--o{ TPictureCode : "包含"
PROJECT ||--o{ TLoggingTaskInfo : "包含"
TLoggingTaskInfo ||--o{ TLoggingTaskContent : "包含"
DEVICE ||--o{ PROJECT : "关联"
```
**图示来源**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [Project.h](file://h/Project.h)
- [Device.h](file://h/Device.h)
- [TestingData.h](file://h/TestingData.h)
- [TdRecord.h](file://h/TdRecord.h)
- [Script.h](file://h/Script.h)
**章节来源**
- [数据库字段修改记录.txt](file://DB/数据库字段修改记录.txt)
- [database_modify.xml](file://database_modify.xml)
## 核心组件
系统的核心数据库组件包括项目(Project)、设备(Device)、测试任务(TD)、测区(TZ)、脚本(Script)和测量记录(TdRecord)等实体。这些组件通过外键关系相互关联,形成了完整的数据模型。数据库操作主要通过DataOperator类实现,该类封装了所有数据库的CRUD操作。
**章节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DataOperator.h](file://h/DataOperator.h)
- [Project.h](file://h/Project.h)
- [Device.h](file://h/Device.h)
## 架构概述
系统采用分层架构,数据库访问层通过ADO技术与Access数据库交互。DataOperator类作为数据访问的核心组件,负责所有数据库操作。UpdateDataBase类负责数据库版本管理和迁移。系统使用连接池技术管理数据库连接,确保多用户并发访问时的性能和稳定性。
```mermaid
graph TB
subgraph "用户界面"
UI[用户界面]
end
subgraph "业务逻辑"
BL[业务逻辑层]
end
subgraph "数据访问"
DAL[数据访问层]
DataOperator[DataOperator]
UpdateDataBase[UpdateDataBase]
end
subgraph "数据库"
DB[(Access数据库)]
end
UI --> BL
BL --> DAL
DAL --> DB
DataOperator --> DB
UpdateDataBase --> DB
```
**图示来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
**章节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
## 详细组件分析
### 数据库实体分析
系统的主要数据库实体包括项目、设备、测试任务、测区、脚本和测量记录。这些实体通过外键关系相互关联,形成了完整的数据模型。
#### 项目实体
项目实体是系统中最顶层的数据单元,包含项目的基本信息和元数据。
```mermaid
classDiagram
class Project {
+DWORD m_dwID
+CString m_szCN
+CString m_szPRname
+CString m_szCNS
+CString m_szDesc
+CString m_szLocation
+CString m_szPRdate
+CString m_szDuration
+CString m_szPS
+CString m_szCS
+CString m_szPM
+CString m_szQAS
+CString m_szStandard
+bool ShowDetailInfo(CListCtrl& proDetailList)
}
```
**图示来源**
- [Project.h](file://h/Project.h)
#### 设备实体
设备实体存储了测量设备的详细信息,包括设备型号、序列号、硬件版本等。
```mermaid
classDiagram
class Device {
+DWORD m_dwID
+UINT m_uState
+UINT m_uType
+BYTE m_ucDevType
+CString m_szDevSN
+CString m_szDevName
+CString m_szModelNO
+CString m_szMDate
+CString m_szHWV
+CString m_szSWV
+CString m_szMBatch
+CString m_szMacAddress
+CString m_szGPS
+BOOL ExecuteOrder(CString strOrder, CString strSign, CString *pStrResult, int nRepeatCnt, int nPollCnt)
+BOOL ExecuteSignleOrder(CString f_szOrder, CString f_szSign, CString *f_szResult, int nCmdPollCnt)
+BOOL ModifyTimeWindow()
+BOOL LockDevice()
+BOOL Reset()
+BOOL DelSynInfo()
+BOOL DelGRInfo()
+BOOL GetSynInfo()
+BOOL GetDevInfo()
+BOOL GetGRInfo()
+int GetPoleCount()
+BOOL Register()
+BOOL Unregister()
+BOOL SendFile(const CString &szHostFilePath, const CString &szLocFilePath, const CString& szLocFileName)
+BOOL ReceiveFile(const CString &szLocFilePath, const CString& szHostFileName, int nRetryCnt)
+bool ShowFLDetailInfo(CListCtrl& devDetailList)
+bool ShowOLDetailInfo(CListCtrl& devDetailList)
+bool ShowGRInfo(CListCtrl& devGRList)
+bool ShowACInfo(CListCtrl& devDetailList)
+BOOL ModifyParameter()
+BOOL ShowCableHeadInfoDlg()
+BOOL IsTheNumofPoleChanged()
+BOOL TestGRForPerPole(int iSN, CStringArray& strResArray)
+BOOL TestGRForAllPole()
+void SetState(UINT uState)
+void SetID(DWORD dwID)
+void PrintLog(CString& strLog)
+int IsExistOtherUserData()
+int CheckGD10Password(CString strGD10Password)
}
```
**图示来源**
- [Device.h](file://h/Device.h)
#### 测试数据实体
测试数据实体存储了测量任务的详细信息和测量结果。
```mermaid
classDiagram
class TestingData {
+DWORD m_dwID
+CString m_szTdName
+CString m_szTdCN
+CString m_szTLocation
+CString m_szPrCN
+CString m_szTzName
+CString m_szTzCN
+DWORD m_dwTzID
+DWORD m_dwSCID
+CString m_szSCCN
+CString m_szSName
+int m_iSType
+int m_iTType
+int m_iTMode
+int m_iEAmount
+int m_iTPAmount
+int m_iCHAmount
+int m_iN
+int m_iTRWave
+int m_iTRFrequency
+int m_iIFrequency
+int m_iSAFrequency
+int m_iCLayout
+float m_fESpace
+CString m_szEDistance
+int m_iWeather
+int m_iWDIR
+float m_fTemperature
+float m_fHeight
+float m_fHumidity
+float m_fTRPeriod
+CString m_szCDate
+CString m_szCTime
+CString m_szTDate
+CString m_szTTime
+int m_iRCamount
+int m_iRDirection
+int m_iCRtime
+CString m_szPM
+CString m_szOP
+CString m_szQA
+CPtrList m_tdChaList
+_WaveCount *m_waveCount
+bool m_bIsCustomToCrossHole
+virtual void UpdataTopography(int f_disType, int f_start, CListCtrl &f_list)
+BOOL ExcuteSql(CString f_sql)
+virtual void GetTimeWindowList(CListCtrl &f_list)
+virtual BOOL ShowTimeWindow(CListCtrl &tdConList, int iTsn)
+void GetORGCStringToArray(CString f_SrcString, CStringArray *f_array)
+void FreeWindowsTime()
+double GetPeriod()
+bool GetTimeWindowInfo(std : : vector<STSigTWInfo>& vtTWInfo)
+void CreateWindowsTime()
+virtual bool CalculateTimeWindows(struct _WinTimeList f_winTimeList, CStringArray *v_orgData, int f_TRwave, int f_Tcycle, int f_Sample, int f_interation, int f_industrial)
+virtual bool CalculateTWInfo(CStringArray *v_orgData, int nFrenquence)
+virtual BOOL DisplayIpCurveGraph()
+CDevice* m_pDevice
+virtual bool ShowGrList(CListCtrl &tdGrList)
+virtual bool ShowConList(CListCtrl &tdConList)
+virtual bool ShowConListByPage(CListCtrl &tdConList, int iSType)
+virtual bool ShowDetailInfo(CListCtrl &tdDetailList)
+virtual BOOL SaveTdToExcelFile(CString f_szFileName)
+virtual BOOL SaveTdToResCEFile(CString f_szFileName)
+virtual BOOL SaveTdToRes2DFile(CString f_szFileName)
+virtual BOOL SaveTdToRes3DFile(CString f_szFileName)
+virtual BOOL SaveTdToCsvFile(CString f_szFileName)
+virtual bool ExportIP2DDataToDat(CString strFile)
+virtual bool ExportIP3DToDatFile(CString strFile)
+virtual BOOL ExportIPDataToTxt(CString strFileName)
+virtual BOOL ExportResDataToTxt(CString strFileName)
+virtual BOOL ExportSpDataToTxt(CString strFileName)
+virtual BOOL Export2dDataToTxtBySort(CString strFileName, int iSortMethod)
+virtual BOOL ExportDataToUrf(CString strFileName)
+void SetCustToCrossHole(bool bFlag)
+virtual BOOL DisplayGraph()
+virtual BOOL DisplayTPSplinesGraph(int iTSN)
+virtual BOOL LoadData(CLinkList<CMedium*>& m_medLinkList)
+inline int CalcuCrossHolePoleID(int iOrgPoleID, int iHoleID, int iHoleFlag, int iMidEamount)
+CTestingData(DWORD dwID, _ConnectionPtr& pConnection)
+virtual ~CTestingData()
+_ConnectionPtr m_pConnection
+CHandleProcessor m_handleProcessor
+double GetCycle(int f_type)
+BOOL SaveOrgDataToDB(DWORD dwTdID)
+BOOL SaveGRDataToDB(DWORD dwTdID)
}
```
**图示来源**
- [TestingData.h](file://h/TestingData.h)
#### 测量记录实体
测量记录实体存储了单次测量的原始数据和计算结果。
```mermaid
classDiagram
class TdRecord {
+DWORD m_dwChID
+int m_iTsn
+int m_iN
+float m_fK
+float m_fI
+float m_fV
+float m_fR0
+float m_fSP
+CString m_Datetime
+CStringArray m_saVRawData
+CStringArray m_saIRawData
+_ConnectionPtr m_pConnection
+float GetMaxAbsV()
+virtual void DisplayRawDataSplines()
+virtual BOOL LoadOrgData()
+virtual float ConvertVOrgData(float fVOrgData)
+float m_fMaxAbsV
+BOOL LoadCEOrgData()
+BOOL Load2DOrgData()
+BOOL Load3DOrgData()
}
```
**图示来源**
- [TdRecord.h](file://h/TdRecord.h)
#### 脚本实体
脚本实体存储了测量任务的配置参数和测量序列。
```mermaid
classDiagram
class Script {
+DWORD m_dwID
+CHandleProcessor m_handleProcessor
+int m_iEAmount
+int m_iSType
+int m_iAR
+virtual void AdjustRecListColumn(int iAR, CListCtrl& sptConListInfo)
+virtual bool ShowSptConInfo(CListCtrl& sptConList)
+virtual bool ShowSptDetailInfo(CListCtrl& sptDetailList)
+virtual bool ShowChannelList(CListCtrl& sptChannelList)
+_ConnectionPtr m_pConnection
}
```
**图示来源**
- [Script.h](file://h/Script.h)
**章节来源**
- [Project.h](file://h/Project.h)
- [Device.h](file://h/Device.h)
- [TestingData.h](file://h/TestingData.h)
- [TdRecord.h](file://h/TdRecord.h)
- [Script.h](file://h/Script.h)
### 数据访问机制分析
系统的数据访问机制基于ADO技术,通过DataOperator类封装了所有数据库操作。
#### 数据库连接流程
系统通过IOManager类中的代码实现数据库连接,使用Microsoft.ACE.OLEDB.12.0提供程序连接Access数据库。
```mermaid
sequenceDiagram
participant UI as "用户界面"
participant IOManager as "IOManager"
participant DataOperator as "DataOperator"
participant ADO as "ADO"
participant DB as "Access数据库"
UI->>IOManager : 选择数据库文件
IOManager->>IOManager : 构建连接字符串
IOManager->>ADO : 创建Connection对象
ADO->>DB : 打开数据库连接
DB-->>ADO : 连接成功
ADO-->>IOManager : 返回连接对象
IOManager->>DataOperator : 传递连接对象
DataOperator->>DataOperator : 初始化数据操作器
DataOperator-->>UI : 准备就绪
```
**图示来源**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
#### 数据库操作流程
DataOperator类提供了完整的CRUD操作接口,封装了ADO的复杂性。
```mermaid
flowchart TD
Start([开始]) --> CreateConnection["创建数据库连接"]
CreateConnection --> OpenConnection["打开连接"]
OpenConnection --> BeginTransaction["开始事务"]
BeginTransaction --> ExecuteOperation["执行数据库操作"]
ExecuteOperation --> CheckResult{"操作成功?"}
CheckResult --> |是| CommitTransaction["提交事务"]
CheckResult --> |否| RollbackTransaction["回滚事务"]
CommitTransaction --> CloseConnection["关闭连接"]
RollbackTransaction --> CloseConnection
CloseConnection --> End([结束])
```
**图示来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
#### 数据库版本管理
系统通过UpdateDataBase类实现数据库版本管理和迁移,确保不同版本间的兼容性。
```mermaid
sequenceDiagram
participant App as "应用程序"
participant UpdateDB as "UpdateDataBase"
participant XML as "database_modify.xml"
participant DB as "数据库"
App->>UpdateDB : 启动时检查版本
UpdateDB->>DB : 查询当前版本
DB-->>UpdateDB : 返回版本信息
UpdateDB->>XML : 加载更新配置
XML-->>UpdateDB : 返回更新信息
UpdateDB->>UpdateDB : 比较版本差异
UpdateDB->>DB : 执行数据库更新
DB-->>UpdateDB : 更新结果
UpdateDB-->>App : 版本更新完成
```
**图示来源**
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [database_modify.xml](file://database_modify.xml)
**章节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
## 依赖分析
系统的主要依赖关系包括数据库文件、ADO库、XML配置文件和日志文件。数据库操作依赖于Microsoft.ACE.OLEDB.12.0提供程序,版本管理依赖于database_modify.xml配置文件。
```mermaid
graph TD
A[Geomative Studio] --> B[Access数据库]
A --> C[msado15.tlh]
A --> D[msado15.tli]
A --> E[database_modify.xml]
A --> F[update_db.log]
B --> G[GeoMativeDB.accdb]
C --> H[ADO库]
D --> I[数据库更新配置]
E --> J[版本管理]
F --> K[操作日志]
```
**图示来源**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [database_modify.xml](file://database_modify.xml)
**章节来源**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
## 性能考虑
系统在数据库性能方面考虑了多个优化策略。首先,使用连接池技术减少数据库连接的创建和销毁开销。其次,通过批量操作减少数据库交互次数。此外,系统在关键查询上建立了适当的索引以提高查询性能。对于大数据量的测量记录,系统采用了分页加载机制,避免一次性加载过多数据导致内存溢出。
## 故障排除指南
当遇到数据库相关问题时,可以参考以下排查步骤:
1. 检查数据库文件是否存在且可访问
2. 验证数据库连接字符串是否正确
3. 检查ADO库是否正确注册
4. 查看update_db.log日志文件中的错误信息
5. 验证数据库版本是否与应用程序兼容
6. 检查数据库文件是否被其他进程锁定
**章节来源**
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
## 结论
Geomative Studio的数据库设计采用了规范化的数据模型,通过项目、设备、测试任务、测区、脚本和测量记录等实体的合理组织,实现了地质测量数据的有效管理。系统通过ADO技术实现了高效的数据访问,并通过完善的版本管理机制确保了数据的兼容性和可维护性。整体设计考虑了性能、可靠性和可扩展性,为地质测量应用提供了坚实的数据基础。
@@ -0,0 +1,201 @@
# CRUD操作实现
<cite>
**本文档引用的文件**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [IOManager.h](file://h/IOManager.h)
- [Project.h](file://h/Project.h)
- [Device.h](file://h/Device.h)
- [Script.h](file://h/Script.h)
- [TestingData.h](file://h/TestingData.h)
</cite>
## 目录
1. [项目结构](#项目结构)
2. [核心CRUD操作](#核心crud操作)
3. [数据加载与持久化](#数据加载与持久化)
4. [实体-关系映射(ORM)逻辑](#实体-关系映射orm逻辑)
5. [SQL注入防护](#sql注入防护)
6. [批量操作优化](#批量操作优化)
7. [数据验证与业务规则](#数据验证与业务规则)
## 项目结构
Geomative Studio项目是一个地质勘探数据管理软件,其核心功能围绕项目、设备、脚本和测试数据的管理。项目采用C++与MFC框架开发,使用Access数据库(.accdb)作为数据存储,通过ADOActiveX Data Objects)技术实现数据库访问。
项目的主要目录结构包括:
- **CACHE/**: 缓存文件目录
- **DB/**: 数据库相关文件
- **Install/**: 安装包和配置文件
- **LOG/**: 日志文件
- **Release/**: 编译输出文件
- **cpp/Managers/**: 核心管理类,包含`IOManager.cpp`等关键文件
- **h/**: 头文件目录,包含`IOManager.h``Project.h`等实体类定义
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1-L2064)
- [IOManager.h](file://h/IOManager.h#L1-L52)
## 核心CRUD操作
`CIOManager`类是实现CRUD(创建、读取、更新、删除)操作的核心。它通过ADO的`_ConnectionPtr``_CatalogPtr`指针与数据库建立连接,并提供`Export``Import`两大核心功能,分别对应数据的导出(持久化)和导入(加载)。
### 创建(Create)与读取(Read)
- **创建**: 通过`Import`方法从外部.accdb文件导入数据,系统会检查数据是否存在,若不存在则执行`INSERT`语句创建新记录。
- **读取**: 使用`_RecordsetPtr`对象执行`SELECT`查询,通过`Open`方法打开记录集,并利用`GetCollect`方法获取字段值。
### 更新(Update)与删除(Delete)
- **更新**: 在`ImportSptToDB`方法中,通过`UPDATE`语句更新`td`表中的`SCID`字段,确保脚本与测试数据的关联。
- **删除**: 虽然代码中未直接体现`DELETE`语句,但通过`DeleteFile`函数在创建导出数据库前删除同名文件,体现了对旧数据的清理。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L2062)
- [IOManager.h](file://h/IOManager.h#L19-L22)
## 数据加载与持久化
数据持久化流程通过`Export`方法启动,该方法创建一个导出对话框,用户选择目标文件后,系统创建一个新的.accdb数据库,并将当前项目中的数据逐级导出。
```mermaid
flowchart TD
A[启动导出] --> B[创建导出对话框]
B --> C{用户选择文件}
C --> |确认| D[创建新数据库]
D --> E[开始事务 BeginTrans]
E --> F[导出项目数据]
F --> G[导出区域数据]
G --> H[导出脚本数据]
H --> I[提交事务 CommitTrans]
I --> J[完成导出]
C --> |取消| K[取消导出]
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L658-L676)
数据加载流程则通过`Import`方法实现,它打开一个文件选择对话框,读取外部.accdb文件的内容,并将其导入到当前数据库中。
```mermaid
flowchart TD
A[启动导入] --> B[选择.accdb文件]
B --> C{文件有效?}
C --> |是| D[开始事务 BeginTrans]
D --> E[导入项目数据]
E --> F[导入区域数据]
F --> G[导入脚本数据]
G --> H[导入测试数据]
H --> I[提交事务 CommitTrans]
I --> J[完成导入]
C --> |否| K[显示错误并取消]
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1521-L1741)
## 实体-关系映射(ORM)逻辑
`CIOManager`类实现了基本的ORM逻辑,将C++中的实体对象(如项目、脚本)映射到数据库表。这种映射主要通过以下方式实现:
1. **对象-表映射**: 每个实体类(如`Project`)对应一个数据库表(如`project`)。
2. **属性-字段映射**: 实体类的成员变量(如`PRname`)对应表的字段。
3. **关系维护**: 通过外键(如`PRCN`)维护实体间的关联关系。
例如,在`CreateExpDatabase`方法中,代码明确地为`project`表定义了所有字段,这正是ORM中“模型”定义的体现。
```mermaid
erDiagram
project {
string CN PK
string PRname
string PRdesc
string location
date PRdate
int duration
string PS
string CS
string PM
string QAS
string standard
}
tz {
string TZname PK
string PRCN FK
string TZdesc
string location
}
td {
string TDname PK
string DESN
string PRCN FK
string TZname FK
string SCCN FK
int TDtype
string HFname
string CFname
int CFRamount
string GRFname
int GRFRamount
}
scon {
string CN PK
string Sname
int Eamount
int CHamount
int TPamount
string definer
date DEdate
string SCdesc
}
project ||--o{ tz : "包含"
project ||--o{ td : "包含"
scon ||--o{ td : "关联"
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L227-L257)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L264-L275)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L282-L307)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L564-L588)
## SQL注入防护
代码中通过**参数化查询**和**数据验证**来防止SQL注入攻击。
1. **参数化查询**: 虽然代码主要使用字符串拼接的`INSERT`语句,但在查询时使用了`Format`函数对输入进行处理,并检查了`VT_NULL`(空值)情况,避免了直接拼接未经处理的用户输入。
2. **数据验证**: 在执行SQL语句前,代码会检查记录集的`GetRecordCount()`,确保数据存在且有效,这在一定程度上防止了恶意数据的注入。
例如,在`ImportProjectToDB`方法中,插入数据前会先检查该项目是否已存在,避免了重复插入和潜在的注入风险。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L2035-L2036)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1514-L1515)
## 批量操作优化
系统通过**事务处理**(Transaction)来优化批量操作的性能和数据一致性。
- **BeginTrans/CommitTrans**: 在`Export``Import`方法的开始和结束处,分别调用了`BeginTrans``CommitTrans`。这确保了所有数据库操作要么全部成功,要么全部回滚(`RollbackTrans`),保证了数据的原子性。
- **批量执行**: 在`ExportDataToAccdbFile``ImportSptToDB`等方法中,通过循环遍历数据并执行`INSERT`语句,实现了批量数据的导出和导入。
这种设计极大地提高了处理大量数据时的效率,避免了频繁的数据库连接和提交开销。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L63-L75)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L177-L188)
## 数据验证与业务规则
在数据持久化过程中,系统应用了多种数据验证和业务规则:
1. **存在性检查**: 在导入数据时,会先查询目标数据库中是否已存在相同记录(通过`CN``ID`等唯一标识),如果存在则跳过,避免数据重复。
2. **外键关联**: 在导入`td`(测试数据)时,会先查询`project``tz`(区域)和`scon`(脚本)表,获取其`ID`,然后将这些`ID`作为外键插入到`td`表中,确保了数据的完整性和关联性。
3. **默认值处理**: 对于可能为空的字段,代码中使用了三元运算符进行判断,如`pRecTd->GetCollect(_T("CFRamount")).vt == VT_NULL ? (int)VAL_ZERO : pRecTd->GetCollect(_T("CFRamount")).iVal`,为`null`值提供了默认处理。
这些规则确保了数据在持久化过程中的准确性和一致性。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1514-L1515)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1574-L1575)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1624-L1625)
@@ -0,0 +1,112 @@
# 事务与错误处理
<cite>
**本文档引用的文件**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [IOManager.h](file://h/IOManager.h)
- [upg_geo_filetrans_log.txt](file://LOG/upg_geo_filetrans_log.txt)
- [msado15.tlh](file://Release/msado15.tlh)
- [msado15.tli](file://Release/msado15.tli)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [Zmodem.cpp](file://cpp/Tools/Zmodem.cpp)
- [FileTransfer.cpp](file://cpp/Tools/FileTransfer.cpp)
</cite>
## 目录
1. [事务管理机制](#事务管理机制)
2. [错误处理机制](#错误处理机制)
3. [日志记录与诊断流程](#日志记录与诊断流程)
4. [常见数据库错误代码与恢复建议](#常见数据库错误代码与恢复建议)
## 事务管理机制
`CIOManager` 类实现了基于 ADO 数据库连接的事务管理机制,用于确保数据操作的原子性、一致性和完整性。该机制主要应用于批量数据导出和导入操作,通过 `BeginTrans``CommitTrans``RollbackTrans` 方法来控制事务的生命周期。
在数据导出操作中,`Export` 方法首先创建一个新的数据库连接,并调用 `BeginTrans` 开始事务。随后,系统将项目、测区、测点等数据分批写入新数据库。如果所有操作均成功完成,则调用 `CommitTrans` 提交事务,使更改永久生效;若在操作过程中发生异常,则通过 `catch` 块捕获 `_com_error` 异常,并调用 `RollbackTrans` 回滚事务,撤销所有已执行的更改,从而保证数据的一致性。
```mermaid
sequenceDiagram
participant 用户 as 用户界面
participant IOManager as CIOManager
participant 数据库 as 目标数据库
用户->>IOManager : 启动导出操作
IOManager->>数据库 : BeginTrans()
IOManager->>数据库 : 写入项目数据
IOManager->>数据库 : 写入测区数据
IOManager->>数据库 : 写入测点数据
alt 操作成功
IOManager->>数据库 : CommitTrans()
IOManager-->>用户 : 导出成功
else 操作失败
IOManager->>数据库 : RollbackTrans()
IOManager-->>用户 : 导出失败,已回滚
end
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L50-L98)
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [IOManager.h](file://h/IOManager.h#L20)
## 错误处理机制
系统采用结构化的异常处理机制来应对数据库连接失败、SQL 执行错误和文件 I/O 异常等情况。核心错误处理逻辑基于 COM 组件的 `_com_error` 异常捕获机制,结合 ADO 错误对象进行详细诊断。
在数据库操作中,任何 ADO 方法调用失败都会抛出 `_com_error` 异常。系统通过 `try-catch` 块捕获这些异常,并根据错误信息采取相应措施。例如,在 `Import` 方法中,如果数据库连接失败或 SQL 查询出错,系统会回滚当前事务并返回错误代码。此外,`TdManager` 类中的 `ExecuteSql` 方法也实现了类似的事务控制和异常处理逻辑,确保复杂业务流程的数据完整性。
对于文件 I/O 操作,`Zmodem.cpp` 文件中的 `ReceiveSingleFile` 函数定义了多种错误状态码(如 `ZERROR``TIMEOUT`),并在发生错误时记录日志并终止传输。`FileTransfer.cpp` 提供了 `error``status` 函数用于输出错误和状态信息,辅助调试和问题定位。
```mermaid
flowchart TD
Start([开始数据库操作]) --> Try["try {<br/>执行数据库操作<br/>}"]
Try --> Catch["catch (_com_error e) {"]
Catch --> Rollback["调用 RollbackTrans()"]
Rollback --> Log["记录错误信息"]
Log --> Return["返回错误代码"]
Try --> Success["操作成功"]
Success --> Commit["调用 CommitTrans()"]
Commit --> End([结束])
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L6818-L6831)
- [Zmodem.cpp](file://cpp/Tools/Zmodem.cpp#L219-L749)
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L6818-L6831)
- [Zmodem.cpp](file://cpp/Tools/Zmodem.cpp#L219-L749)
- [FileTransfer.cpp](file://cpp/Tools/FileTransfer.cpp#L28-L46)
## 日志记录与诊断流程
系统通过日志文件 `upg_geo_filetrans_log.txt` 记录网络请求失败等关键错误信息。当系统尝试访问更新服务器 `update.geomative.com` 时,若域名解析失败,会将详细的错误信息(包括时间戳、错误描述和 URL)写入日志文件。这种机制有助于诊断网络连接问题和服务器不可达情况。
日志条目格式包含时间戳、线程 ID、错误级别和具体错误消息,便于追踪问题发生的时间和上下文。例如,日志中记录了两次 `curl_perform failed!` 错误,均因无法解析主机名导致,这表明可能存在 DNS 配置问题或网络中断。
**Section sources**
- [upg_geo_filetrans_log.txt](file://LOG/upg_geo_filetrans_log.txt#L1-L3)
## 常见数据库错误代码与恢复建议
根据 ADO 错误代码定义,以下是常见数据库错误及其恢复建议:
| 错误代码 | 错误常量 | 描述 | 恢复建议 |
|---------|---------|------|--------|
| 3004 | adErrWriteFile | 写文件错误 | 检查磁盘空间和文件权限 |
| 3219 | adErrIllegalOperation | 非法操作 | 检查操作是否在正确状态下执行 |
| 3246 | adErrInTransaction | 正在事务中 | 确保事务正确提交或回滚 |
| 3704 | adErrObjectClosed | 对象已关闭 | 在使用前检查对象是否已打开 |
| 3705 | adErrObjectOpen | 对象已打开 | 确保对象在使用后正确关闭 |
| 3706 | adErrProviderNotFound | 未找到提供程序 | 检查数据库驱动安装 |
| 3709 | adErrInvalidConnection | 无效连接 | 重新建立数据库连接 |
| 3714 | adErrInvalidTransaction | 无效事务 | 检查事务状态并重新开始 |
当遇到数据库错误时,建议首先检查连接状态,然后根据具体错误代码采取相应措施。对于可恢复错误(如连接中断),可尝试重新连接并重试操作;对于不可恢复错误(如权限不足),需联系管理员解决。
**Section sources**
- [msado15.tlh](file://Release/msado15.tlh#L613-L654)
- [msado15.tli](file://Release/msado15.tli#L1976-L1992)
@@ -0,0 +1,293 @@
# 数据导入导出
<cite>
**本文档引用的文件**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [IOManager.h](file://h/IOManager.h)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [DataOperator.h](file://h/DataOperator.h)
- [excel.cpp](file://cpp/Tools/excel.cpp)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp)
- [IAP-GD10.bat](file://tools/IAP-GD10.bat)
</cite>
## 目录
1. [引言](#引言)
2. [数据导入导出架构](#数据导入导出架构)
3. [核心组件分析](#核心组件分析)
4. [文件解析与数据映射](#文件解析与数据映射)
5. [批处理脚本集成](#批处理脚本集成)
6. [错误处理机制](#错误处理机制)
7. [结论](#结论)
## 引言
Geomative Studio 提供了全面的数据导入导出功能,支持多种数据格式(Excel、CSV、TXT、URF)的转换。本文档详细描述了CIOManager支持的多种数据格式的导入导出机制,包括文件解析流程、数据映射规则和格式转换策略。文档结合DataOperator类的实现,展示从外部文件读取数据并持久化到数据库的完整流程,以及从数据库导出为指定格式的实现细节。同时提供批处理脚本(如IAP-GD10.bat)与核心功能的集成方式说明,并包含格式不兼容、编码问题和数据丢失预防等错误处理机制。
## 数据导入导出架构
Geomative Studio的数据导入导出功能采用分层架构设计,主要由IOManager、DataOperator和文件操作工具类组成。IOManager负责管理导入导出的整体流程,DataOperator处理具体的数据操作,而各种文件操作类(如COperTxtFile、COperUrfFile)则负责特定格式的文件读写。
```mermaid
graph TB
subgraph "用户界面"
UI[数据导入导出界面]
end
subgraph "业务逻辑层"
IOManager[CIOManager]
DataOperator[CDataOperator]
end
subgraph "数据访问层"
FileOperator[文件操作工具]
Database[数据库]
end
subgraph "文件格式"
Excel[Excel文件]
CSV[CSV文件]
TXT[TXT文件]
URF[URF文件]
end
UI --> IOManager
IOManager --> DataOperator
DataOperator --> FileOperator
FileOperator --> Excel
FileOperator --> CSV
FileOperator --> TXT
FileOperator --> URF
DataOperator --> Database
Database --> FileOperator
```
**Diagram sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L79-L95)
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L19-L35)
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L19-L27)
## 核心组件分析
### IOManager类
CIOManager类是数据导入导出功能的核心管理器,负责协调整个导入导出流程。它提供了Export和Import两个主要方法,分别处理数据导出和导入操作。在导出过程中,IOManager创建一个新的Access数据库文件,并将项目、测区、测点等数据结构化地导出到该数据库中。
```mermaid
classDiagram
class CIOManager {
+_ConnectionPtr m_pConnection
+ADOX : : _CatalogPtr m_pCatalog
+CHandleProcessor m_handleProcessor
+CStateProcessor m_stateProcessor
+UINT Export()
+UINT Import()
+_ConnectionPtr CreateExpDatabase(CString szFileName)
+void ExportDataToAccdbFile(_ConnectionPtr pExpConnection, CTreeCtrl& dmsTree)
+void ExportProjectToAccdbFile(_ConnectionPtr pExpConnection, DWORD dwProID)
+void ExportTzToAccdbFile(_ConnectionPtr pExpConnection, DWORD dwTzID)
+void ExportRspTdToAccdbFile(_ConnectionPtr pExpConnection, DWORD dwTdID)
+void ExportIpspTdToAccdbFile(_ConnectionPtr pExpConnection, DWORD dwTdID)
+void ImportProjectToDB(_ConnectionPtr pImpConnection)
+void ImportTzToDB(_ConnectionPtr pImpConnection)
+void ImportSptToDB(_ConnectionPtr pImpConnection)
+void ImportRspTdToDB(_ConnectionPtr pImpConnection)
+void ImportIpspTdToDB(_ConnectionPtr pImpConnection)
}
class CDataOperator {
+_ConnectionPtr m_pConnection
+CStateProcessor m_stateProcessor
+CHandleProcessor m_handleProcessor
+DWORD m_dwItemHandle
+bool m_BatchExportFlag
+UINT ExportIpCETdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIp2DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIp3DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIpCETdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIp2DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIp3DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIP2DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIP3DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportIP1DToTxt(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRspCETdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp2DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp3DTdToExcel(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRspCETdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp2DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp3DTdToCSV(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp2DTdToUrf(CNavDataView *pNavDataView, CString f_szFileName)
+UINT ExportRsp3DTdToUrf(CNavDataView *pNavDataView, CString f_szFileName)
}
CIOManager --> CDataOperator : "使用"
```
**Diagram sources**
- [IOManager.h](file://h/IOManager.h#L15-L49)
- [DataOperator.h](file://h/DataOperator.h#L23-L171)
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L98)
- [IOManager.h](file://h/IOManager.h#L15-L49)
### DataOperator类
CDataOperator类负责具体的数据操作,包括将数据导出为各种格式(Excel、CSV、TXT、URF)。它通过调用相应的文件操作工具类来实现不同格式的文件写入。该类提供了丰富的导出方法,支持一维、二维和三维电阻率及激电数据的导出。
**Section sources**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L79-L95)
- [DataOperator.h](file://h/DataOperator.h#L23-L171)
## 文件解析与数据映射
### Excel和CSV文件处理
Excel和CSV文件的处理通过excel.cpp文件中的类实现。系统使用COM接口与Excel应用程序交互,实现数据的读写操作。对于CSV文件,系统采用文本文件处理方式,通过逗号分隔符解析数据。
```mermaid
flowchart TD
Start([开始导出]) --> CheckFormat["检查导出格式"]
CheckFormat --> |Excel| CreateExcel["创建Excel工作簿"]
CheckFormat --> |CSV| CreateCSV["创建CSV文件"]
CheckFormat --> |TXT| CreateTXT["创建TXT文件"]
CheckFormat --> |URF| CreateURF["创建URF文件"]
CreateExcel --> WriteHeader["写入表头"]
CreateCSV --> WriteHeader
CreateTXT --> WriteHeader
CreateURF --> WriteHeader
WriteHeader --> GetData["从数据库获取数据"]
GetData --> FormatData["格式化数据"]
FormatData --> WriteData["写入数据行"]
WriteData --> CheckMore["是否有更多数据?"]
CheckMore --> |是| WriteData
CheckMore --> |否| SaveFile["保存文件"]
SaveFile --> End([导出完成])
```
**Diagram sources**
- [excel.cpp](file://cpp/Tools/excel.cpp#L19-L800)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L100-L112)
**Section sources**
- [excel.cpp](file://cpp/Tools/excel.cpp#L19-L800)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L100-L112)
### TXT文件处理
TXT文件处理由COperTxtFile类负责,该类提供了灵活的文本文件写入功能。系统允许设置参数宽度,确保数据对齐。写入时,不足宽度的部分用空格填充,保证了文件的可读性。
```mermaid
sequenceDiagram
participant UI as "用户界面"
participant DataOperator as "CDataOperator"
participant OperTxtFile as "COperTxtFile"
participant File as "文件系统"
UI->>DataOperator : 请求导出TXT文件
DataOperator->>DataOperator : 获取选中的测点数据
DataOperator->>OperTxtFile : 创建COperTxtFile实例
OperTxtFile->>OperTxtFile : 设置参数宽度
OperTxtFile->>File : 打开文件进行写入
File-->>OperTxtFile : 文件句柄
OperTxtFile->>DataOperator : 准备数据数组
DataOperator->>OperTxtFile : 提供格式化数据
OperTxtFile->>File : 写入数据行
loop 每一行数据
OperTxtFile->>File : 写入格式化行
end
OperTxtFile->>File : 关闭文件
DataOperator-->>UI : 返回导出结果
```
**Diagram sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L19-L166)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L110-L112)
**Section sources**
- [OperTxtFile.cpp](file://cpp/Tools/OperTxtFile.cpp#L19-L166)
### URF文件处理
URFUniversal Resistivity data File)文件处理由COperUrfFile类实现。该类支持多种电极阵列配置的URF文件生成,包括温纳-施伦贝格尔(Wenner-Schlumberger)、交叉孔(Cross Hole)等装置类型。系统根据不同的装置类型生成相应的电极坐标信息。
```mermaid
flowchart TD
Start([开始URF导出]) --> CheckAR["检查装置类型"]
CheckAR --> |温纳-施伦贝格尔| WenSch["生成Wenner-Schlumberger电极坐标"]
CheckAR --> |交叉孔| CrossHole["生成Cross Hole电极坐标"]
CheckAR --> |自定义| Custom["生成自定义电极坐标"]
WenSch --> CalcCoord["计算电极坐标"]
CrossHole --> CalcCoord
Custom --> CalcCoord
CalcCoord --> CreateFile["创建URF文件"]
CreateFile --> WriteHeader["写入URF文件头"]
WriteHeader --> WriteElec["写入电极信息"]
WriteElec --> WriteData["写入测量数据"]
WriteData --> SaveFile["保存URF文件"]
SaveFile --> End([URF导出完成])
```
**Diagram sources**
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L31-L800)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L146-L148)
**Section sources**
- [OperUrfFile.cpp](file://cpp/Tools/OperUrfFile.cpp#L31-L800)
## 批处理脚本集成
批处理脚本(如IAP-GD10.bat)与核心功能的集成主要通过命令行调用实现。这些脚本通常用于固件更新或设备配置,通过调用DFU工具来完成设备的编程操作。
```mermaid
sequenceDiagram
participant User as "用户"
participant BatchScript as "批处理脚本"
participant DFUTool as "DFU工具"
participant Device as "GD10设备"
User->>BatchScript : 运行IAP-GD10.bat
BatchScript->>BatchScript : 延迟10秒等待设备连接
BatchScript->>DFUTool : 调用DfuCreateFile创建DFU文件
DFUTool-->>BatchScript : 生成APP.dfu文件
BatchScript->>DFUTool : 调用DfuSeCommand烧录固件
DFUTool->>Device : 通过USB传输固件
Device-->>DFUTool : 确认烧录完成
DFUTool-->>BatchScript : 返回烧录结果
BatchScript->>BatchScript : 删除临时DFU文件
BatchScript-->>User : 完成固件更新
```
**Diagram sources**
- [IAP-GD10.bat](file://tools/IAP-GD10.bat#L1-L16)
**Section sources**
- [IAP-GD10.bat](file://tools/IAP-GD10.bat#L1-L16)
## 错误处理机制
系统实现了全面的错误处理机制,确保在数据导入导出过程中出现问题时能够及时发现并处理。错误处理包括格式验证、编码处理、数据完整性检查等方面。
### 格式兼容性检查
在导入数据时,系统首先检查文件格式是否兼容。对于Access数据库文件,系统会验证是否存在特定的版本标识符,确保文件结构正确。
```mermaid
flowchart TD
Start([开始导入]) --> CheckFile["检查文件是否存在"]
CheckFile --> |不存在| ShowError1["显示文件不存在错误"]
CheckFile --> |存在| OpenConnection["打开数据库连接"]
OpenConnection --> |失败| ShowError2["显示连接错误"]
OpenConnection --> |成功| CheckVersion["检查数据库版本"]
CheckVersion --> |版本不匹配| ShowError3["显示版本不兼容错误"]
CheckVersion --> |版本匹配| BeginTransaction["开始事务"]
BeginTransaction --> ImportData["导入数据"]
ImportData --> |成功| Commit["提交事务"]
ImportData --> |失败| Rollback["回滚事务"]
Commit --> End([导入成功])
Rollback --> ShowError4["显示导入失败错误"]
ShowError1 --> End
ShowError2 --> End
ShowError3 --> End
ShowError4 --> End
```
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L133-L158)
### 编码问题处理
系统在处理文本文件时,会自动检测文件编码,并在必要时进行转换。对于中文环境,系统使用适当的字符集确保中文字符的正确显示。
### 数据丢失预防
为防止数据丢失,系统在执行导入导出操作时使用数据库事务。所有操作都在事务中进行,只有当所有操作都成功完成时才会提交事务,否则回滚到操作前的状态。
**Section sources**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L177-L188)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L63-L77)
## 结论
Geomative Studio的数据导入导出功能提供了全面的解决方案,支持多种数据格式的转换。系统采用分层架构设计,各组件职责明确,便于维护和扩展。通过IOManager和DataOperator类的协同工作,实现了从数据库到各种文件格式的高效转换。同时,系统提供了完善的错误处理机制,确保数据操作的安全性和可靠性。批处理脚本的集成进一步增强了系统的自动化能力,为用户提供了便捷的操作体验。
@@ -0,0 +1,342 @@
# 数据库连接管理
<cite>
**本文引用的文件**
- [IOManager.h](file://h/IOManager.h)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
- [msado15.tlh](file://Release/msado15.tlh)
- [msado15.tli](file://Release/msado15.tli)
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp)
- [ProManager.cpp](file://cpp/Managers/ProManager.cpp)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
## 简介
本文件聚焦于基于ADOActiveX Data Objects)的数据库连接管理,围绕CIOManager类在GeomativeStudio中的职责展开,系统性说明其如何初始化并管理与Access数据库(.accdb)的连接,涵盖连接字符串配置、事务与命令执行、连接生命周期管理、异常处理与恢复、以及多线程场景下的同步注意事项。同时结合实际代码路径,给出连接建立、健康检查与异常恢复的实现要点,并提供性能调优建议与资源释放策略,帮助读者在不直接阅读源码的情况下理解整体机制。
## 项目结构
- 应用程序入口负责COM初始化、数据库连接创建与打开、以及各业务管理器实例化。
- CIOManager作为数据导入导出的核心协调者,持有主数据库连接与目录对象,负责导出新数据库、批量写入与事务控制。
- 多个业务管理器(如CTdManager、CProManager等)共享主连接,执行各自的数据操作。
- ADO类型头文件提供Connection/Command/Recordset等接口属性与方法声明,便于理解超时、隔离级别、状态等能力。
```mermaid
graph TB
App["应用程序入口<br/>初始化COM/创建连接"] --> Conn["_ConnectionPtr<br/>主连接"]
App --> Catalog["ADOX::_CatalogPtr<br/>目录对象"]
Conn --> IO["CIOManager<br/>导入/导出协调"]
Conn --> TdMgr["CTdManager<br/>TD相关操作"]
Conn --> ProMgr["CProManager<br/>项目/区域操作"]
Conn --> SptOp["CSptOperator<br/>测点/脚本操作"]
Conn --> DataOp["CDataOperator<br/>数据删除/更新"]
Conn --> Test["CProblemZone::TestingData<br/>测试数据写入"]
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [IOManager.h](file://h/IOManager.h#L15-L51)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L256)
- [msado15.tlh](file://Release/msado15.tlh#L3990-L4029)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [IOManager.h](file://h/IOManager.h#L15-L51)
## 核心组件
- CIOManager:负责导入/导出流程的协调,持有主连接与目录对象;导出时创建新的目标数据库并批量写入,使用事务保证一致性。
- 主连接(_ConnectionPtr):由应用程序入口创建并打开,承载所有业务操作。
- 目录对象(ADOX::_CatalogPtr):用于创建新数据库、定义表结构与列约束。
- 命令对象(_CommandPtr):在事务内执行SQL语句,绑定ActiveConnection,避免重复创建连接。
- 记录集(_RecordsetPtr):用于查询、更新、参数化查询等。
章节来源
- [IOManager.h](file://h/IOManager.h#L15-L51)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L256)
- [msado15.tlh](file://Release/msado15.tlh#L3990-L4029)
## 架构总览
下图展示了应用启动时的连接初始化与关键业务流程之间的交互关系。
```mermaid
sequenceDiagram
participant App as "应用程序入口"
participant Conn as "_ConnectionPtr"
participant Cat as "ADOX : : _CatalogPtr"
participant IO as "CIOManager"
participant Td as "CTdManager"
participant Pro as "CProManager"
participant Spt as "CSptOperator"
participant Data as "CDataOperator"
App->>App : 初始化COM
App->>Conn : 创建连接实例
App->>Conn : 打开连接(连接字符串)
App->>Cat : 设置活动连接/创建数据库
App->>IO : 传入主连接与目录对象
IO->>IO : 导出流程(事务/批量写入)
App->>Td : 使用主连接执行TD相关操作
App->>Pro : 使用主连接执行项目/区域操作
App->>Spt : 使用主连接执行测点/脚本操作
App->>Data : 使用主连接执行数据删除/更新
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L256)
- [IOManager.h](file://h/IOManager.h#L15-L51)
## 详细组件分析
### CIOManager类与连接管理
- 连接注入:构造函数接收主连接与目录对象,确保后续导出流程可直接复用现有连接。
- 导入流程:
- 弹窗选择外部Access文件,拼接连接字符串(包含提供程序与数据库密码),创建连接并打开。
- 检查目标数据库是否包含特定版本表,否则提示错误并回滚。
- 在主连接上开启事务,依次导入项目、区域、测点、响应/电阻率数据,最后提交或回滚。
- 导出流程:
- 创建新数据库(通过目录对象),定义项目、区域、TD、TD头、参数、响应/电阻率、IPSP、GR、Scon、Channel、Script、dbversion等表及列。
- 在新连接上开启事务,按树形结构批量导出数据,最后提交并关闭连接。
- 关键点:
- 所有命令对象(_CommandPtr)均将ActiveConnection指向主连接,减少连接创建成本。
- 导入/导出均使用事务,失败时回滚并清理临时文件。
```mermaid
classDiagram
class CIOManager {
+Import() UINT
+Export() UINT
-CreateExpDatabase(szFileName) _ConnectionPtr
-ExportDataToAccdbFile(pExpConnection, dmsTree) void
-ExportProjectToAccdbFile(pExpConnection, dwProID) void
-ExportTzToAccdbFile(pExpConnection, dwTzID) void
-ExportRspTdToAccdbFile(pExpConnection, dwTdID) void
-ExportIpspTdToAccdbFile(pExpConnection, dwTdID) void
-ExportSptToAccdbFile(pExpConnection, sptList) void
-ExportTdHeadInfoToAccdbFile(pExpConnection, dwTdID, szTdName, szDeSn) void
-ImportProjectToDB(pImpConnection) void
-ImportTzToDB(pImpConnection) void
-ImportRspTdToDB(pImpConnection) void
-ImportIpspTdToDB(pImpConnection) void
-ImportSptToDB(pImpConnection) void
-InitialExpDmsTree(dmsTree) void
-InitialExpSptList(sptList) void
-m_pConnection : _ConnectionPtr
-m_pCatalog : ADOX : : _CatalogPtr
}
```
图表来源
- [IOManager.h](file://h/IOManager.h#L15-L51)
章节来源
- [IOManager.h](file://h/IOManager.h#L15-L51)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L656)
### 应用程序启动与关闭时的连接处理
- 启动阶段:
- 初始化COM后创建主连接实例,拼接连接字符串(提供程序、数据源、数据库密码),打开连接。
- 设置Jet OLEDB锁数量上限,提升并发写入能力。
- 创建目录对象并设置活动连接,为导出创建新数据库做准备。
- 实例化各业务管理器(CTdManager、CProManager、CSptOperator等),统一使用主连接。
- 关闭阶段:
- 代码中未见显式析构关闭主连接的逻辑。建议在应用退出前显式Close()并置空指针,防止资源泄漏。
```mermaid
flowchart TD
Start(["应用启动"]) --> InitCOM["初始化COM"]
InitCOM --> CreateConn["创建主连接实例"]
CreateConn --> OpenConn["打开连接(连接字符串)"]
OpenConn --> SetProps["设置Jet OLEDB属性"]
SetProps --> CreateCat["创建目录对象并设置活动连接"]
CreateCat --> NewMgrs["实例化业务管理器(共享主连接)"]
NewMgrs --> Ready(["就绪"])
Ready --> Shutdown(["应用退出"]) --> CloseConn["关闭主连接(建议)"]
CloseConn --> End(["结束"])
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L426-L431)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L426-L431)
### 连接字符串配置与数据库密码
- 主连接字符串包含提供程序、数据源与数据库密码,确保访问受保护的数据库文件。
- 导出目标数据库同样使用相同提供程序与密码策略,保证一致性。
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L284)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L218-L223)
### 事务与批量写入
- 导入:在主连接上BeginTrans,逐项导入后Commit;若异常则Rollback并关闭外部连接。
- 导出:在新连接上BeginTrans,批量写入后Commit;异常时Rollback并删除临时文件。
- 命令对象(_CommandPtr)统一绑定ActiveConnection,减少连接创建与上下文切换。
章节来源
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L104)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1392-L1448)
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp#L704-L711)
### 连接生命周期管理
- 生命周期:
- 创建:应用程序入口创建主连接实例。
- 打开:使用连接字符串打开连接。
- 使用:各业务模块共享主连接执行查询/更新。
- 关闭:建议在应用退出前显式Close()并置空指针。
- 资源释放:
- 记录集、命令对象在使用完毕后应关闭或释放,避免句柄泄露。
- 导出失败时删除临时文件,确保磁盘空间与一致性。
章节来源
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L35-L104)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L256)
### 多线程环境下的连接同步机制
- 当前代码未显式使用互斥量或临界区保护ADO连接。由于ADO连接对象并非线程安全,跨线程访问存在风险。
- 建议:
- 为主连接加全局互斥或在业务层串行化关键操作。
- 对频繁写入的场景,考虑拆分连接或使用只读连接用于查询,写入使用独立连接。
- 避免在UI线程长时间占用连接,必要时将耗时操作移至后台线程并做好异常捕获与回滚。
章节来源
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1392-L1448)
- [Global.cpp](file://cpp/Main/Global.cpp#L48-L58)
### 连接超时设置
- ADO支持ConnectionTimeout与CommandTimeout属性,可通过类型头文件提供的接口设置。
- 实践建议:
- 对长事务或大批量写入,适当提高CommandTimeout。
- 对网络型数据库或远程文件,合理设置ConnectionTimeout,避免阻塞UI线程。
章节来源
- [msado15.tlh](file://Release/msado15.tlh#L3990-L4029)
- [msado15.tli](file://Release/msado15.tli#L1925-L1954)
### 健康检查与异常恢复
- 健康检查:
- 可通过查询版本表或执行简单SQL验证连接可用性。
- 监控连接状态(State属性)与错误集合(Errors)。
- 异常恢复:
- 导入/导出均使用try/catch捕获_com_error,失败时Rollback、Close并清理临时文件。
- 对外部数据库校验失败时,提示用户并终止流程。
```mermaid
flowchart TD
Start(["开始操作"]) --> Try["尝试执行SQL/事务"]
Try --> Ok{"成功?"}
Ok --> |是| Commit["提交事务/关闭连接"]
Ok --> |否| Catch["捕获_com_error"]
Catch --> Rollback["回滚事务/关闭连接"]
Rollback --> Clean["清理临时文件/资源"]
Clean --> Notify["提示用户/记录日志"]
Notify --> End(["结束"])
```
图表来源
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1392-L1448)
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp#L704-L711)
章节来源
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1392-L1448)
- [SptOperator.cpp](file://cpp/Operator/SptOperator.cpp#L704-L711)
### 典型业务流程示例(代码路径)
- 导入外部数据库并写入主库:
- 连接字符串拼接与打开:[GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L284)
- 版本表校验与事务控制:[IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L199)
- 写入命令绑定ActiveConnection[IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1418-L1422)
- 导出新数据库并批量写入:
- 创建数据库与表结构:[IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L656)
- 事务内批量写入:[IOManager.cpp](file://cpp/Managers/IOManager.cpp#L658-L727)
- 删除TD相关数据:
- 查询与删除命令绑定ActiveConnection[TdManager.cpp](file://cpp/Managers/TdManager.cpp#L6452-L6482)
- 更新测试数据:
- 参数化更新命令:[TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L365-L405)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L284)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L199)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L206-L727)
- [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L6452-L6482)
- [TestingData.cpp](file://cpp/ProblemZone/TestingData.cpp#L365-L405)
## 依赖关系分析
- 组件耦合:
- CIOManager依赖主连接与目录对象,承担导入/导出协调职责。
- 各业务管理器(CTdManager、CProManager、CSptOperator、CDataOperator)共享主连接,降低连接数。
- 外部依赖:
- ADO/ADOX类型头文件提供Connection/Command/Recordset等接口能力。
- 提供程序为Microsoft.ACE.OLEDB.12.0,适用于Access 2007+格式。
```mermaid
graph LR
A["GeoMative.cpp<br/>创建/打开主连接"] --> B["CIOManager<br/>导入/导出协调"]
A --> C["CTdManager<br/>TD操作"]
A --> D["CProManager<br/>项目/区域操作"]
A --> E["CSptOperator<br/>测点/脚本操作"]
A --> F["CDataOperator<br/>数据删除/更新"]
B --> G["ADOX::Catalog<br/>创建数据库/表结构"]
B --> H["ADO::Connection/Command/Recordset<br/>事务/命令/查询"]
```
图表来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [IOManager.h](file://h/IOManager.h#L15-L51)
- [msado15.tlh](file://Release/msado15.tlh#L3990-L4029)
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L279-L309)
- [IOManager.h](file://h/IOManager.h#L15-L51)
## 性能考量
- 连接池策略:
- 当前采用单主连接共享模式,未使用显式连接池。对于高并发写入,建议:
- 将只读查询与写入分离,减少锁竞争。
- 对热点写入操作使用后台线程串行化,避免UI阻塞。
- 锁与并发:
- 已设置Jet OLEDB最大锁数,有助于提升并发写入稳定性。
- 超时与隔离:
- 合理设置CommandTimeout与ConnectionTimeout,避免长时间阻塞。
- 隔离级别可根据业务需求调整(默认即可满足多数场景)。
- I/O优化:
- 批量写入优先使用参数化命令与事务,减少往返次数。
- 导出时一次性创建表结构,避免多次DDL变更。
[本节为通用指导,无需列出具体文件来源]
## 故障排查指南
- 常见问题与定位:
- 连接失败:检查连接字符串、提供程序版本与数据库密码;查看错误描述与错误码。
- 导入失败:确认外部数据库包含版本表;异常时Rollback并清理临时文件。
- 导出失败:确认目录权限与磁盘空间;失败时删除临时文件并提示用户。
- 排查步骤:
- 捕获_com_error,输出ErrorMessage与Description,结合日志定位。
- 校验连接状态(State)与错误集合(Errors)。
- 对长时间运行的事务,适当提高CommandTimeout并分批提交。
章节来源
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L293-L310)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L101-L204)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L1392-L1448)
## 结论
CIOManager通过主连接与目录对象实现了对Access数据库的高效导入/导出管理,配合事务与命令对象,确保了数据一致性与性能。应用程序入口负责连接的创建与打开,并在业务层共享该连接。尽管当前未实现显式连接池与严格的多线程同步,但通过合理的事务控制、参数化命令与资源释放策略,已能满足大多数业务场景。建议在后续版本中完善连接超时设置、引入线程同步与连接池策略,并在应用退出时显式关闭主连接,进一步提升稳定性与安全性。
@@ -0,0 +1,230 @@
# 数据访问层
<cite>
**本文档引用的文件**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp)
- [IOManager.h](file://h/IOManager.h)
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp)
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp)
- [database_modify.xml](file://database_modify.xml)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
Geomative Studio 是一个用于地球物理数据采集和分析的软件系统。本架构文档详细描述了其数据访问层的实现机制,重点分析基于 ADOActiveX Data Objects)的数据库访问实现。文档涵盖了 CIOManager 类如何封装数据库连接、查询执行、事务管理和错误处理,解释了数据持久化模式、对象-关系映射策略以及关键数据库操作(如项目导入导出、设备信息同步、测量数据存储)的实现细节。同时,文档还提供了性能优化策略和异常处理机制。
## 项目结构
Geomative Studio 项目采用典型的分层架构,将业务逻辑、数据访问和用户界面分离。数据访问层主要由 `Managers``Operator` 目录下的类构成,它们通过 ADO 技术与 Microsoft Access 数据库(`.accdb`)进行交互。`Managers` 目录包含核心管理类(如 `CIOManager`, `CProManager`),负责高层次的业务逻辑和数据协调。`Operator` 目录则包含具体的操作类(如 `CDataOperator`, `CSynOperator`),直接执行数据库的 CRUD(创建、读取、更新、删除)操作。
```mermaid
graph TB
subgraph "用户界面"
UI[视图/对话框]
end
subgraph "业务逻辑层"
Managers[Managers目录<br>CIOManager等]
Operators[Operator目录<br>DataOperator等]
end
subgraph "数据访问层"
ADO[ADO组件<br>_ConnectionPtr<br>_RecordsetPtr]
end
subgraph "数据存储"
DB[(GeoMativeDB.accdb)]
end
UI --> Managers
Managers --> Operators
Operators --> ADO
ADO --> DB
```
**图表来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L233-L283)
- [IOManager.h](file://h/IOManager.h#L15-L49)
**本节来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L233-L283)
- [IOManager.h](file://h/IOManager.h#L15-L49)
## 核心组件
数据访问层的核心是 `CIOManager` 类,它作为整个系统与数据库交互的中心枢纽。该类在应用程序启动时被初始化,并接收一个全局的 `_ConnectionPtr` 对象,确保所有数据库操作都通过同一个连接进行,从而提高效率并保证事务的一致性。`CIOManager` 封装了数据库的导入、导出功能,并通过 `ADOX::_CatalogPtr` 对象在运行时动态创建和管理数据库结构。
**本节来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L430)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L22-L28)
## 架构概述
系统的数据访问架构基于 ADO 技术,利用 COM 接口实现对 Access 数据库的访问。`CIOManager` 类在 `GeoMativeApp``InitInstance` 方法中被创建,并在整个应用程序生命周期内持有数据库连接。其他管理器(如 `CTdManager`, `CProManager`)在初始化时也会接收同一个 `_ConnectionPtr`,形成一个共享连接的架构。这种设计减少了连接开销,但也要求开发者在多线程环境下谨慎处理连接的并发访问。
```mermaid
sequenceDiagram
participant App as "GeoMativeApp"
participant IO as "CIOManager"
participant Pro as "CProManager"
participant Td as "CTdManager"
participant DB as "Access数据库"
App->>App : 启动程序
App->>App : 创建_ConnectionPtr
App->>IO : 创建CIOManager(连接, 目录)
App->>Pro : 创建CProManager(连接)
App->>Td : 创建CTdManager(连接)
IO->>DB : 执行导入/导出操作
Pro->>DB : 管理项目数据
Td->>DB : 管理测量任务
```
**图表来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L233-L283)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L22-L28)
## 详细组件分析
### CIOManager 分析
`CIOManager` 类是数据访问层的核心,负责数据库的连接管理、事务控制和高级数据操作。
#### 类图
```mermaid
classDiagram
class CIOManager {
+_ConnectionPtr m_pConnection
+ADOX : : _CatalogPtr m_pCatalog
+CHandleProcessor m_handleProcessor
+CStateProcessor m_stateProcessor
+CIOManager(_ConnectionPtr&, ADOX : : _CatalogPtr)
+~CIOManager()
+UINT Export()
+UINT Import()
+_ConnectionPtr CreateExpDatabase(CString)
+void ExportDataToAccdbFile(_ConnectionPtr, CTreeCtrl&)
+void ImportProjectToDB(_ConnectionPtr)
}
CIOManager --> _ConnectionPtr : "使用"
CIOManager --> ADOX._CatalogPtr : "使用"
CIOManager --> CHandleProcessor : "包含"
CIOManager --> CStateProcessor : "包含"
```
**图表来源**
- [IOManager.h](file://h/IOManager.h#L15-L49)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L22-L28)
#### 导入导出流程
`CIOManager` 提供了完整的项目导入导出功能。导出时,它首先通过 `CreateExpDatabase` 方法创建一个新的 `.accdb` 文件,并使用 `ADOX::_CatalogPtr` 定义所有必要的表结构(如 `project`, `tz`, `td` 等),然后将当前数据库中的数据逐批写入新文件。导入时,它会验证源文件的版本,然后在一个事务中将数据从源数据库读取并插入到主数据库中,确保数据的原子性和一致性。
```mermaid
flowchart TD
Start([开始导入]) --> CheckFile["验证文件格式和版本"]
CheckFile --> |有效| BeginTrans["开始数据库事务"]
CheckFile --> |无效| ReturnError["返回错误"]
BeginTrans --> ReadData["从源数据库读取数据"]
ReadData --> InsertData["向主数据库插入数据"]
InsertData --> Commit["提交事务"]
InsertData --> Rollback["回滚事务"]
Commit --> End([导入成功])
Rollback --> EndError([导入失败])
style Commit stroke:#0f0,stroke-width:2px
style Rollback stroke:#f00,stroke-width:2px
```
**图表来源**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204)
**本节来源**
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204)
- [IOManager.h](file://h/IOManager.h#L19-L20)
### 数据持久化模式
系统采用了一种混合的持久化模式。对于复杂的业务对象(如 `Project`, `TestingData`),系统在内存中维护对象模型,并通过 `CDataOperator` 等操作类将对象的状态映射到数据库表的行和列上。这种映射关系是隐式的,通过 SQL 查询和记录集(`_RecordsetPtr`)来实现,而不是一个成熟的 ORM(对象关系映射)框架。
#### 对象-关系映射策略
数据加载和保存流程通常遵循以下模式:
1. **加载**:构造一个 SQL 查询语句,打开一个 `_RecordsetPtr`,然后遍历记录集,为每一行创建相应的 C++ 对象,并将数据库字段的值赋给对象的属性。
2. **保存**:当对象状态改变时,生成相应的 `INSERT`, `UPDATE`, 或 `DELETE` SQL 语句,并通过 `_CommandPtr` 执行。
例如,在 `CDataOperator::CreateProjectInDB` 中,通过 `m_pConnection->BeginTrans()` 开启事务,调用业务方法创建项目,然后通过 SQL 查询获取新创建的项目信息并更新 UI 树形控件,最后提交事务。
**本节来源**
- [DataOperator.cpp](file://cpp/Operator/DataOperator.cpp#L618-L668)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L97-L200)
### 关键数据库操作实现
#### 项目导入导出
如上所述,`CIOManager` 类的 `Export``Import` 方法实现了完整的项目级数据迁移。导出过程会创建一个包含所有必要表结构的新数据库文件,并将选中的项目、测区、测量任务等数据复制过去。导入过程则会检查源文件的兼容性,并安全地将数据合并到当前数据库中。
#### 设备信息同步
设备信息同步由 `CSynOperator` 类处理。该类在构造时接收数据库连接,其 `Syn` 方法会创建一个同步对话框(`COpSynDlg`),允许用户选择设备进行同步。同步逻辑在对话框内部实现,通过查询 `device` 表来获取设备列表,并与现场设备进行数据交换。
**本节来源**
- [SynOperator.cpp](file://cpp/Operator/SynOperator.cpp#L21-L55)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L100-L204)
#### 测量数据存储
测量数据的存储是一个关键操作,由 `CTaskDataOper` 类负责。当创建一个新的测量任务(如一维任务)时,`Create1DTask` 方法会:
1. 查询脚本信息(`scon` 表)以获取电极数量等参数。
2. 获取默认测区 ID。
3.`td` 表中插入一条新的任务记录。
4.`tdchannel` 表中插入通道信息。
5. 批量将脚本中的测量点(`script1d` 表)复制到任务的测量点表(`td1dcon`)中。
整个过程在一个数据库事务中完成,确保了数据的完整性。
**本节来源**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L97-L200)
## 依赖分析
数据访问层严重依赖于 ADO 和 ADOX 库,这些库通过 `msado15.tlh``msadox.tlh` 头文件在编译时引入。`CIOManager` 依赖于 `CHandleProcessor``CStateProcessor` 来处理句柄和状态转换。业务逻辑层的各个管理器(`CProManager`, `CTdManager` 等)都直接依赖于 `CIOManager` 建立的数据库连接。
```mermaid
graph LR
IOManager --> ADO
IOManager --> ADOX
IOManager --> HandleProcessor
IOManager --> StateProcessor
ProManager --> IOManager
TdManager --> IOManager
DevManager --> IOManager
ExecManager --> IOManager
```
**图表来源**
- [IOManager.h](file://h/IOManager.h#L8-L9)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L425-L430)
**本节来源**
- [IOManager.h](file://h/IOManager.h#L8-L9)
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L425-L430)
## 性能考虑
系统在性能方面采取了以下策略:
1. **连接复用**:全局使用单个 `_ConnectionPtr`,避免了频繁建立和断开数据库连接的开销。
2. **事务管理**:对于批量操作(如项目导入、任务创建),使用 `BeginTrans`/`CommitTrans` 将多个 SQL 操作包装在一个事务中,显著提高了写入性能。
3. **批量操作**:在数据迁移时,使用 `INSERT INTO ... SELECT` 语句进行批量数据复制,而不是逐条插入。
4. **连接参数优化**:在连接字符串中设置了 `Jet OLEDB:Max Locks Per File`,以避免在高并发操作时出现锁冲突。
**本节来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L282)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L63-L75)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L148-L197)
## 故障排除指南
数据访问层的异常处理主要通过捕获 `_com_error` 异常来实现。当 ADO 操作失败时,会立即回滚当前事务(`RollbackTrans`),关闭连接,并向用户显示错误信息。例如,在数据库连接失败或 SQL 执行出错时,系统会弹出消息框提示用户。此外,`UpdateDataBase` 类在数据库升级时也会进行详细的日志记录(`update_db.log`),便于排查版本更新问题。
**本节来源**
- [GeoMative.cpp](file://cpp/Main/GeoMative.cpp#L293-L309)
- [IOManager.cpp](file://cpp/Managers/IOManager.cpp#L80-L86)
- [UpdateDataBase.cpp](file://cpp/Operator/UpdateDataBase.cpp#L26)
## 结论
Geomative Studio 的数据访问层基于 ADO 技术构建,设计清晰,职责明确。`CIOManager` 作为核心组件,有效地封装了数据库连接和事务管理,为上层业务逻辑提供了稳定的数据访问接口。系统通过共享连接、事务和批量操作等策略保证了数据操作的性能和一致性。尽管其对象-关系映射较为基础,但对于当前的应用场景是足够且高效的。未来的改进方向可以考虑引入更现代的 ORM 框架或迁移到更强大的数据库系统以支持更大的数据量和更复杂的查询。