266 lines
8.1 KiB
Markdown
266 lines
8.1 KiB
Markdown
# Data Model: WCTDataMiner
|
||
|
||
> WCTDataMiner 数据库模型规格,采用维度表设计,消除数据冗余
|
||
|
||
---
|
||
|
||
## 文档索引
|
||
|
||
### 维度表
|
||
|
||
| 文档 | 说明 |
|
||
|------|------|
|
||
| [TX面板维度](./entities/TxPanel维度.md) | TX面板类型维度 |
|
||
| [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) | 实体间关系定义 |
|
||
|
||
---
|
||
|
||
## 实体列表
|
||
|
||
### 维度表(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判定结果"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 设计说明
|
||
|
||
### 星型模型架构
|
||
|
||
本设计采用星型模型(Star Schema):
|
||
|
||
- **维度表**:存储可能重复的属性值(面板、硬件版本、软件版本、RX类型)
|
||
- **事实表**:存储外键组合和度量数据
|
||
|
||
**优势**:
|
||
- 维度值只存一份,消除冗余
|
||
- 维度可复用,相同硬件版本在不同场景中引用同一记录
|
||
- 查询可按维度灵活筛选和分组
|
||
|
||
### 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 WCTDataMiner.Models;
|
||
|
||
namespace WCTDataMiner.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 | |