Files
coco df489d5640 a
2026-07-03 16:05:30 +08:00

8.0 KiB
Raw Permalink Blame History

CRUD操作实现

**本文档引用的文件** - [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)

目录

  1. 项目结构
  2. 核心CRUD操作
  3. 数据加载与持久化
  4. 实体-关系映射(ORM)逻辑
  5. SQL注入防护
  6. 批量操作优化
  7. 数据验证与业务规则

项目结构

Geomative Studio项目是一个地质勘探数据管理软件,其核心功能围绕项目、设备、脚本和测试数据的管理。项目采用C++与MFC框架开发,使用Access数据库(.accdb)作为数据存储,通过ADOActiveX Data Objects)技术实现数据库访问。

项目的主要目录结构包括:

  • CACHE/: 缓存文件目录
  • DB/: 数据库相关文件
  • Install/: 安装包和配置文件
  • LOG/: 日志文件
  • Release/: 编译输出文件
  • cpp/Managers/: 核心管理类,包含IOManager.cpp等关键文件
  • h/: 头文件目录,包含IOManager.hProject.h等实体类定义

Diagram sources

核心CRUD操作

CIOManager类是实现CRUD(创建、读取、更新、删除)操作的核心。它通过ADO的_ConnectionPtr_CatalogPtr指针与数据库建立连接,并提供ExportImport两大核心功能,分别对应数据的导出(持久化)和导入(加载)。

创建(Create)与读取(Read)

  • 创建: 通过Import方法从外部.accdb文件导入数据,系统会检查数据是否存在,若不存在则执行INSERT语句创建新记录。
  • 读取: 使用_RecordsetPtr对象执行SELECT查询,通过Open方法打开记录集,并利用GetCollect方法获取字段值。

更新(Update)与删除(Delete)

  • 更新: 在ImportSptToDB方法中,通过UPDATE语句更新td表中的SCID字段,确保脚本与测试数据的关联。
  • 删除: 虽然代码中未直接体现DELETE语句,但通过DeleteFile函数在创建导出数据库前删除同名文件,体现了对旧数据的清理。

Section sources

数据加载与持久化

数据持久化流程通过Export方法启动,该方法创建一个导出对话框,用户选择目标文件后,系统创建一个新的.accdb数据库,并将当前项目中的数据逐级导出。

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

数据加载流程则通过Import方法实现,它打开一个文件选择对话框,读取外部.accdb文件的内容,并将其导入到当前数据库中。

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

实体-关系映射(ORM)逻辑

CIOManager类实现了基本的ORM逻辑,将C++中的实体对象(如项目、脚本)映射到数据库表。这种映射主要通过以下方式实现:

  1. 对象-表映射: 每个实体类(如Project)对应一个数据库表(如project)。
  2. 属性-字段映射: 实体类的成员变量(如PRname)对应表的字段。
  3. 关系维护: 通过外键(如PRCN)维护实体间的关联关系。

例如,在CreateExpDatabase方法中,代码明确地为project表定义了所有字段,这正是ORM中“模型”定义的体现。

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

SQL注入防护

代码中通过参数化查询数据验证来防止SQL注入攻击。

  1. 参数化查询: 虽然代码主要使用字符串拼接的INSERT语句,但在查询时使用了Format函数对输入进行处理,并检查了VT_NULL(空值)情况,避免了直接拼接未经处理的用户输入。
  2. 数据验证: 在执行SQL语句前,代码会检查记录集的GetRecordCount(),确保数据存在且有效,这在一定程度上防止了恶意数据的注入。

例如,在ImportProjectToDB方法中,插入数据前会先检查该项目是否已存在,避免了重复插入和潜在的注入风险。

Section sources

批量操作优化

系统通过事务处理Transaction)来优化批量操作的性能和数据一致性。

  • BeginTrans/CommitTrans: 在ExportImport方法的开始和结束处,分别调用了BeginTransCommitTrans。这确保了所有数据库操作要么全部成功,要么全部回滚(RollbackTrans),保证了数据的原子性。
  • 批量执行: 在ExportDataToAccdbFileImportSptToDB等方法中,通过循环遍历数据并执行INSERT语句,实现了批量数据的导出和导入。

这种设计极大地提高了处理大量数据时的效率,避免了频繁的数据库连接和提交开销。

Section sources

数据验证与业务规则

在数据持久化过程中,系统应用了多种数据验证和业务规则:

  1. 存在性检查: 在导入数据时,会先查询目标数据库中是否已存在相同记录(通过CNID等唯一标识),如果存在则跳过,避免数据重复。
  2. 外键关联: 在导入td(测试数据)时,会先查询projecttz(区域)和scon(脚本)表,获取其ID,然后将这些ID作为外键插入到td表中,确保了数据的完整性和关联性。
  3. 默认值处理: 对于可能为空的字段,代码中使用了三元运算符进行判断,如pRecTd->GetCollect(_T("CFRamount")).vt == VT_NULL ? (int)VAL_ZERO : pRecTd->GetCollect(_T("CFRamount")).iVal,为null值提供了默认处理。

这些规则确保了数据在持久化过程中的准确性和一致性。

Section sources