# ploss_record 实体 > 所属模块:[数据模型概览](../概览.md) --- ## 1. 表定义 **表名**:`ploss_record` **描述**:存储 Ploss FOD 格式解析数据,对应两行日志格式: ``` pow_loss = X, delta_p = Y FOD-> (1) (2) ... (16) ``` --- ## 2. 字段定义 | 列名 | 类型 | 约束 | 说明 | |------|------|------|------| | id | UUID | PK, NOT NULL | 主键 | | scenario_id | UUID | FK, NOT NULL | 关联测试场景 | | pow_loss | INT | NULL | 第一行:功率损耗值 | | delta_p | INT | NULL | 第一行:功率差值 | | field_1 | INT | NOT NULL | Field1(语义待定义) | | field_2 | INT | NOT NULL | Field2(语义待定义) | | field_3 | INT | NOT NULL | Field3(语义待定义) | | field_4 | INT | NOT NULL | Field4: RX power - 接收端功率 | | field_5 | INT | NOT NULL | Field5: TX power - 发射端功率 | | field_6 | INT | NOT NULL | Field6(语义待定义) | | field_7 | INT | NOT NULL | Field7(语义待定义) | | field_8 | INT | NOT NULL | Field8(语义待定义) | | field_9 | INT | NOT NULL, DEFAULT 0 | Field9: ploss - 功率损耗计算值 | | field_10 | INT | NOT NULL, DEFAULT 0 | Field10: threshold - 阈值 | | field_11 | INT | NOT NULL | Field11: 触发次数 - 当 Field9 > Field10 时计数,超过5次触发FOD保护 | | field_12 | INT | NOT NULL | Field12: PFOD result 标志 - 触发时置位 | | field_13 | INT | NOT NULL, DEFAULT 0 | Field13(语义待定义) | | field_14 | INT | NOT NULL, DEFAULT 0 | Field14(语义待定义) | | field_15 | INT | NOT NULL, DEFAULT 0 | Field15(语义待定义) | | field_16 | INT | NOT NULL, DEFAULT 0 | Field16(语义待定义) | | is_deleted | BOOLEAN | NOT NULL, DEFAULT FALSE | 软删除标记 | | created_at | TIMESTAMP | NOT NULL, DEFAULT NOW() | 创建时间 | > **字段语义**以 `PlossRecord` 实体注释为准。 --- ## 3. 外键 | 外键 | 引用表 | 说明 | |------|--------|------| | scenario_id | test_scenario.id | 关联测试场景(必需) | --- ## 4. 派生字段 > **注意**:以下字段不落库,查询时动态计算 | 字段 | 计算公式 | 说明 | |------|----------|------| | margin | field_10 - field_9 | 安全余量(>0 安全,<0 危险) | > **使用限制**:`Margin` 属性通过 EF Core `Ignore()` 排除映射,仅用于内存计算。不可在数据库查询中直接使用(如 `WHERE Margin > 0`),需改用 `WHERE (field_10 - field_9) > 0` 或先加载到内存再计算。 --- ## 5. 索引 | 索引名 | 字段 | 用途 | |--------|------|------| | idx_ploss_scenario | scenario_id | 按测试场景查询 | | idx_ploss_field_2 | field_2 | 字段查询 | | idx_ploss_field_7 | field_7 | 字段查询 | | idx_ploss_field_8 | field_8 | 字段查询 | | idx_ploss_field_10 | field_10 | 字段查询 | | idx_ploss_pow_loss | pow_loss | 第一行损耗值查询 | | idx_ploss_delta_p | delta_p | 第一行功率差值查询 | --- ## 6. EF Core 模型 ### 实体类 ```csharp // Domain/Local/PlossRecord.cs namespace Gpulse.WCT.DataAnalyzer.Core.Domain.Local; public class PlossRecord { public Guid Id { get; set; } = Guid.NewGuid(); public Guid ScenarioId { get; set; } // ===== 第一行字段(nullable,兼容旧数据) ===== /// 功率损耗值(来自第一行) public int? PowLoss { get; set; } /// 功率差值(来自第一行) public int? DeltaP { get; set; } // ===== 第二行字段(16个通用字段,均支持负数) ===== public int Field1 { get; set; } public int Field2 { get; set; } public int Field3 { get; set; } /// Field4: RX power - 接收端功率 public int Field4 { get; set; } /// Field5: TX power - 发射端功率 public int Field5 { get; set; } public int Field6 { get; set; } public int Field7 { get; set; } public int Field8 { get; set; } /// Field9: ploss - 功率损耗计算值 public int Field9 { get; set; } /// Field10: threshold - 阈值 public int Field10 { get; set; } /// Field11: 触发次数 - 当 Field9 > Field10(ploss 大于阈值)时计数,超过5次触发FOD保护 public int Field11 { get; set; } /// Field12: PFOD result 标志 - 触发时置位 public int Field12 { get; set; } public int Field13 { get; set; } public int Field14 { get; set; } public int Field15 { get; set; } public int Field16 { get; set; } public bool IsDeleted { get; set; } = false; public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // Navigation Properties public TestScenario Scenario { get; set; } = null!; /// 派生属性:安全余量(不落库) = Field10 - Field9 public int Margin => Field10 - Field9; } ``` ### 配置类 ```csharp // Infrastructure/LocalData/Configurations/PlossRecordConfiguration.cs using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Gpulse.WCT.DataAnalyzer.Core.Domain.Local; namespace Gpulse.WCT.DataAnalyzer.Core.Infrastructure.LocalData.Configurations; public class PlossRecordConfiguration : IEntityTypeConfiguration { public void Configure(EntityTypeBuilder builder) { builder.ToTable("ploss_record"); builder.HasKey(e => e.Id); builder.Property(e => e.Id).HasColumnName("id"); builder.Property(e => e.ScenarioId) .IsRequired() .HasColumnName("scenario_id"); // ===== 第一行字段(nullable) ===== builder.Property(e => e.PowLoss).IsRequired(false).HasColumnName("pow_loss"); builder.Property(e => e.DeltaP).IsRequired(false).HasColumnName("delta_p"); // ===== 第二行字段(通用命名) ===== builder.Property(e => e.Field1).IsRequired().HasColumnName("field_1"); builder.Property(e => e.Field2).IsRequired().HasColumnName("field_2"); builder.Property(e => e.Field3).IsRequired().HasColumnName("field_3"); builder.Property(e => e.Field4).IsRequired().HasColumnName("field_4"); builder.Property(e => e.Field5).IsRequired().HasColumnName("field_5"); builder.Property(e => e.Field6).IsRequired().HasColumnName("field_6"); builder.Property(e => e.Field7).IsRequired().HasColumnName("field_7"); builder.Property(e => e.Field8).IsRequired().HasColumnName("field_8"); builder.Property(e => e.Field9).IsRequired().HasDefaultValue(0).HasColumnName("field_9"); builder.Property(e => e.Field10).IsRequired().HasDefaultValue(0).HasColumnName("field_10"); builder.Property(e => e.Field11).IsRequired().HasColumnName("field_11"); builder.Property(e => e.Field12).IsRequired().HasColumnName("field_12"); builder.Property(e => e.Field13).IsRequired().HasDefaultValue(0).HasColumnName("field_13"); builder.Property(e => e.Field14).IsRequired().HasDefaultValue(0).HasColumnName("field_14"); builder.Property(e => e.Field15).IsRequired().HasDefaultValue(0).HasColumnName("field_15"); builder.Property(e => e.Field16).IsRequired().HasDefaultValue(0).HasColumnName("field_16"); builder.Property(e => e.IsDeleted) .IsRequired() .HasDefaultValue(false) .HasColumnName("is_deleted"); builder.Property(e => e.CreatedAt) .IsRequired() .HasDefaultValueSql("datetime('now')") .HasColumnName("created_at"); // 派生属性不落库 builder.Ignore(e => e.Margin); // 索引 builder.HasIndex(e => e.ScenarioId).HasDatabaseName("idx_ploss_scenario"); builder.HasIndex(e => e.Field2).HasDatabaseName("idx_ploss_field_2"); builder.HasIndex(e => e.Field7).HasDatabaseName("idx_ploss_field_7"); builder.HasIndex(e => e.Field8).HasDatabaseName("idx_ploss_field_8"); builder.HasIndex(e => e.Field10).HasDatabaseName("idx_ploss_field_10"); builder.HasIndex(e => e.PowLoss).HasDatabaseName("idx_ploss_pow_loss"); builder.HasIndex(e => e.DeltaP).HasDatabaseName("idx_ploss_delta_p"); // 关系配置 builder.HasOne(e => e.Scenario) .WithMany(e => e.PlossRecords) .HasForeignKey(e => e.ScenarioId) .OnDelete(DeleteBehavior.Cascade); // 全局查询过滤器 builder.HasQueryFilter(e => !e.IsDeleted); } } ``` --- ## 7. 动态阈值表 > 阈值根据 RxPower 动态查表(不落库,业务规则) | Rx Power 区间 | Threshold | 备注 | |---------------|-----------|------| | 0-5000 mW | 350 mW | 低功率最敏感 | | 5000-10000 mW | 500 mW | | | 10000-15000 mW | 750 mW | | | 15000-30000 mW | 1000 mW | | | 30000-50000 mW | 1250 mW | 高功率 |