# 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` Fluent API 配置,实体类保持纯净 POCO: ```csharp // Data/WctMinerDbContext.cs using Microsoft.EntityFrameworkCore; using WCTDataMiner.Models; namespace WCTDataMiner.Data; public class WctMinerDbContext : DbContext { public WctMinerDbContext(DbContextOptions options) : base(options) { } public DbSet TxPanels => Set(); public DbSet TxHardwares => Set(); public DbSet TxSoftwares => Set(); public DbSet RxTypes => Set(); public DbSet TestScenarios => Set(); public DbSet QfodRecords => Set(); public DbSet PlossRecords => Set(); protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 自动应用所有 IEntityTypeConfiguration 配置 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 |