docs: 更新项目架构与数据模型文档
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
# Data Model: Gpulse.WCT.DataAnalyzer
|
||||
|
||||
> Gpulse.WCT.DataAnalyzer 数据库模型规格,采用维度表设计,消除数据冗余
|
||||
> 双数据库数据模型:本地解析库 + 正式发布库,相互独立。
|
||||
|
||||
---
|
||||
|
||||
## 文档索引
|
||||
|
||||
### 维度表
|
||||
### 本地库(local.db)
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
@@ -14,253 +14,74 @@
|
||||
| [TX硬件版本维度](./entities/TxHardware维度.md) | TX硬件版本维度 |
|
||||
| [TX软件版本维度](./entities/TxSoftware维度.md) | TX软件版本维度 |
|
||||
| [RX类型维度](./entities/RxType维度.md) | RX类型维度 |
|
||||
|
||||
### 事实表
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [测试场景实体](./entities/测试场景.md) | 测试场景(外键组合) |
|
||||
| [Qfod 记录实体](./entities/Qfod记录.md) | Qfod 检测数据 |
|
||||
| [Ploss 记录实体](./entities/Ploss记录.md) | Ploss FOD 数据 |
|
||||
| [关系说明](./关系说明.md) | 实体间关系定义 |
|
||||
| [关系说明](./关系说明.md) | 本地库实体间关系 |
|
||||
|
||||
### 发布库(release.db)
|
||||
|
||||
| 实体 | 表 | 说明 |
|
||||
|------|----|------|
|
||||
| ChargingParameterRecord | charging_parameter | 正式充电参数记录 |
|
||||
|
||||
---
|
||||
|
||||
## 实体列表
|
||||
|
||||
### 维度表(4张)
|
||||
|
||||
| 表名 | 职责 | 关键字段 |
|
||||
|------|------|----------|
|
||||
| tx_panel | TX面板类型维度 | name (UNIQUE) |
|
||||
| tx_hardware | TX硬件版本维度 | version (UNIQUE) |
|
||||
| tx_software | TX软件版本维度 | version (UNIQUE) |
|
||||
| rx_type | RX类型维度 | name (UNIQUE) |
|
||||
|
||||
### 事实表(3张)
|
||||
|
||||
| 表名 | 职责 | 关键字段 |
|
||||
|------|------|----------|
|
||||
| test_scenario | 测试场景组合 | 4个维度外键 + test_purpose + test_date |
|
||||
| qfod_record | Qfod 检测数据 | scenario_id, delta_q, fod_type |
|
||||
| ploss_record | Ploss FOD 数据 | scenario_id, ploss, threshold |
|
||||
|
||||
---
|
||||
|
||||
## ER 关系图
|
||||
## 架构概览
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
%% 本地库
|
||||
tx_panel ||--o{ test_scenario : "引用"
|
||||
tx_hardware ||--o{ test_scenario : "引用"
|
||||
tx_software ||--o{ test_scenario : "引用"
|
||||
rx_type ||--o{ test_scenario : "引用"
|
||||
|
||||
test_scenario ||--o{ qfod_record : "包含"
|
||||
test_scenario ||--o{ ploss_record : "包含"
|
||||
|
||||
tx_panel {
|
||||
uuid id PK "主键"
|
||||
varchar name UK "面板类型"
|
||||
}
|
||||
|
||||
tx_hardware {
|
||||
uuid id PK "主键"
|
||||
varchar version UK "硬件版本"
|
||||
}
|
||||
|
||||
tx_software {
|
||||
uuid id PK "主键"
|
||||
varchar version UK "软件版本"
|
||||
}
|
||||
|
||||
rx_type {
|
||||
uuid id PK "主键"
|
||||
varchar name UK "RX类型"
|
||||
}
|
||||
|
||||
test_scenario {
|
||||
uuid id PK "主键"
|
||||
uuid tx_panel_id FK "面板外键"
|
||||
uuid tx_hardware_id FK "硬件外键"
|
||||
uuid tx_software_id FK "软件外键"
|
||||
uuid rx_type_id FK "RX外键"
|
||||
varchar test_purpose "测试目的"
|
||||
date test_date "测试日期"
|
||||
int test_sequence "测试序号"
|
||||
int qfod_count "Qfod记录数"
|
||||
int ploss_count "Ploss记录数"
|
||||
}
|
||||
|
||||
qfod_record {
|
||||
uuid id PK "主键"
|
||||
uuid scenario_id FK "场景外键"
|
||||
tinyint charger_index "充电器索引"
|
||||
tinyint coil_index "线圈索引"
|
||||
int delta_q "Q值变化量"
|
||||
float current_q "当前Q值"
|
||||
float raw_q "原始Q值"
|
||||
tinyint fod_type "异物类型"
|
||||
}
|
||||
|
||||
ploss_record {
|
||||
uuid id PK "主键"
|
||||
uuid scenario_id FK "场景外键"
|
||||
tinyint rx_type "接收端类型"
|
||||
smallint rx_power "接收端功率"
|
||||
smallint tx_power "发射端功率"
|
||||
int ploss "计算损耗值"
|
||||
int threshold "阈值"
|
||||
smallint fod_result "FOD判定结果"
|
||||
%% 发布库(独立)
|
||||
charging_parameter {
|
||||
uuid id PK
|
||||
varchar car_factory UK
|
||||
varchar car_model UK
|
||||
varchar phone_brand UK
|
||||
varchar phone_model UK
|
||||
double power_350mw
|
||||
double power_500mw
|
||||
double power_750mw
|
||||
double power_1000mw
|
||||
double power_1250mw
|
||||
double power_1500mw
|
||||
double power_1750mw
|
||||
double power_2000mw
|
||||
double power_2250mw
|
||||
double q_value
|
||||
double q_base_value
|
||||
double pq_coefficient
|
||||
double resonance_frequency
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
框外是本地库,框内是发布库——两库之间没有外键或导航属性。
|
||||
|
||||
## 设计说明
|
||||
|
||||
### 星型模型架构
|
||||
### 本地库:星型模型
|
||||
|
||||
本设计采用星型模型(Star Schema):
|
||||
- 维度表:TxPanel, TxHardware, TxSoftware, RxType
|
||||
- 事实表:TestScenario, QfodRecord, PlossRecord
|
||||
- 所有表支持软删除(is_deleted + query filter)
|
||||
|
||||
- **维度表**:存储可能重复的属性值(面板、硬件版本、软件版本、RX类型)
|
||||
- **事实表**:存储外键组合和度量数据
|
||||
### 发布库:独立扁平表
|
||||
|
||||
**优势**:
|
||||
- 维度值只存一份,消除冗余
|
||||
- 维度可复用,相同硬件版本在不同场景中引用同一记录
|
||||
- 查询可按维度灵活筛选和分组
|
||||
- 一个业务多维表,无外键依赖
|
||||
- 唯一键:(car_factory, car_model, phone_brand, phone_model)
|
||||
- 无 is_deleted、无软删除、无审计字段
|
||||
- 更新时间 updated_at 记录发布记录的最后变更时间
|
||||
|
||||
### test_purpose 处理
|
||||
### 隔离原则
|
||||
|
||||
`test_purpose` 直接存储在场景表中,不拆分维度表,原因:
|
||||
- 测试目的描述较自由,不适合标准化为维度
|
||||
- 便于用户灵活输入
|
||||
|
||||
### 场景唯一性
|
||||
|
||||
场景表设置唯一约束,相同属性组合不重复创建:
|
||||
|
||||
```
|
||||
UNIQUE(tx_panel_id, tx_hardware_id, tx_software_id, rx_type_id, test_purpose, test_date, test_sequence)
|
||||
```
|
||||
|
||||
### 软删除设计
|
||||
|
||||
所有表均包含 `is_deleted` 字段,支持软删除:
|
||||
|
||||
| 字段名 | 类型 | 约束 | 说明 |
|
||||
|--------|------|------|------|
|
||||
| is_deleted | BOOLEAN | NOT NULL, DEFAULT FALSE | 软删除标记 |
|
||||
|
||||
**删除行为**:
|
||||
- 删除操作设置 `is_deleted = true`,不物理删除数据
|
||||
- 查询时默认过滤已删除记录(`WHERE is_deleted = false`)
|
||||
- 支持数据恢复和审计追溯
|
||||
|
||||
**查询示例**:
|
||||
```csharp
|
||||
// 默认查询(不含已删除)
|
||||
var activeRecords = context.TxPanels
|
||||
.Where(t => !t.IsDeleted)
|
||||
.ToList();
|
||||
|
||||
// 包含已删除记录
|
||||
var allRecords = context.TxPanels
|
||||
.IgnoreQueryFilters()
|
||||
.ToList();
|
||||
|
||||
// 软删除操作
|
||||
public async Task SoftDeleteAsync(Guid id)
|
||||
{
|
||||
var entity = await context.TxPanels.FindAsync(id);
|
||||
if (entity != null)
|
||||
{
|
||||
entity.IsDeleted = true;
|
||||
await context.SaveChangesAsync();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 实体配置方式
|
||||
|
||||
采用 `IEntityTypeConfiguration<T>` Fluent API 配置,实体类保持纯净 POCO:
|
||||
|
||||
```csharp
|
||||
// Data/WctMinerDbContext.cs
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Gpulse.WCT.DataAnalyzer.Models;
|
||||
|
||||
namespace Gpulse.WCT.DataAnalyzer.Data;
|
||||
|
||||
public class WctMinerDbContext : DbContext
|
||||
{
|
||||
public WctMinerDbContext(DbContextOptions<WctMinerDbContext> options)
|
||||
: base(options) { }
|
||||
|
||||
public DbSet<TxPanel> TxPanels => Set<TxPanel>();
|
||||
public DbSet<TxHardware> TxHardwares => Set<TxHardware>();
|
||||
public DbSet<TxSoftware> TxSoftwares => Set<TxSoftware>();
|
||||
public DbSet<RxType> RxTypes => Set<RxType>();
|
||||
public DbSet<TestScenario> TestScenarios => Set<TestScenario>();
|
||||
public DbSet<QfodRecord> QfodRecords => Set<QfodRecord>();
|
||||
public DbSet<PlossRecord> PlossRecords => Set<PlossRecord>();
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
// 自动应用所有 IEntityTypeConfiguration<T> 配置
|
||||
modelBuilder.ApplyConfigurationsFromAssembly(typeof(WctMinerDbContext).Assembly);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **数据库兼容性说明**:
|
||||
> - `HasDefaultValueSql("NOW()")` 适用于 PostgreSQL
|
||||
> - 若使用 SQLite,需改为 `HasDefaultValueSql("datetime('now')")`
|
||||
> - 若使用 MySQL,需改为 `HasDefaultValueSql("NOW()")`(MySQL 也支持)
|
||||
> - 若使用 SQL Server,需改为 `HasDefaultValueSql("GETDATE()")`
|
||||
|
||||
**配置类列表**:
|
||||
|
||||
| 配置类 | 文件路径 | 说明 |
|
||||
|--------|----------|------|
|
||||
| TxPanelConfiguration | Data/Configurations/TxPanelConfiguration.cs | TX面板维度 |
|
||||
| TxHardwareConfiguration | Data/Configurations/TxHardwareConfiguration.cs | TX硬件版本维度 |
|
||||
| TxSoftwareConfiguration | Data/Configurations/TxSoftwareConfiguration.cs | TX软件版本维度 |
|
||||
| RxTypeConfiguration | Data/Configurations/RxTypeConfiguration.cs | RX类型维度 |
|
||||
| TestScenarioConfiguration | Data/Configurations/TestScenarioConfiguration.cs | 测试场景 |
|
||||
| QfodRecordConfiguration | Data/Configurations/QfodRecordConfiguration.cs | Qfod记录 |
|
||||
| PlossRecordConfiguration | Data/Configurations/PlossRecordConfiguration.cs | Ploss记录 |
|
||||
|
||||
> **迁移注意事项**:从 DataAnnotations `DateTime.UtcNow` 迁移到 `HasDefaultValueSql("NOW()")` 后,测试代码需注意:未显式设置 `CreatedAt` 时,值由数据库生成而非 C# 运行时。单元测试中需 mock 数据库或显式设置值。
|
||||
|
||||
### 系统日志处理
|
||||
|
||||
解析过程中的错误日志通过 Serilog 记录到系统日志文件,不存入业务数据库。
|
||||
|
||||
---
|
||||
|
||||
## 数据量估算
|
||||
|
||||
| 表 | 增长方式 | 预估规模 |
|
||||
|------|----------|----------|
|
||||
| tx_panel | 预置数据 | 7 条(固定枚举) |
|
||||
| tx_hardware | 随版本迭代 | 10-50 条/年 |
|
||||
| tx_software | 随版本迭代 | 10-50 条/年 |
|
||||
| rx_type | 随设备增加 | 20-100 条/年 |
|
||||
| test_scenario | 随测试批次 | 3,650 条/年 |
|
||||
| qfod_record | 随测试数据 | 3.6M-18M 条/年 |
|
||||
| ploss_record | 随测试数据 | 3.6M-18M 条/年 |
|
||||
|
||||
---
|
||||
|
||||
## 假设/歧义标注
|
||||
|
||||
| 标注 | 内容 |
|
||||
|------|------|
|
||||
| [A] | 使用 UUID 作为主键 |
|
||||
| [?] | FOD Type 具体编码含义需确认 |
|
||||
| [?] | Ploss 日志格式与实际日志对应关系需确认 |
|
||||
| [!] | ploss 负数表示安全,正数可能触发 FOD |
|
||||
- 代码中两个实体的命名空间不同(Domain.Models)
|
||||
- 两个 DbContext 不共享 DbSet
|
||||
- 发布库不从本地库继承实体配置
|
||||
- aggregate 通过纯值映射,不依赖导航属性
|
||||
Reference in New Issue
Block a user