a
This commit is contained in:
@@ -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)作为数据存储,通过ADO(ActiveX 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文件处理
|
||||
URF(Universal 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. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
本文件聚焦于基于ADO(ActiveX 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 是一个用于地球物理数据采集和分析的软件系统。本架构文档详细描述了其数据访问层的实现机制,重点分析基于 ADO(ActiveX 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 框架或迁移到更强大的数据库系统以支持更大的数据量和更复杂的查询。
|
||||
Reference in New Issue
Block a user