EF中如何将Info实体升级为Review并更新鉴别器与ReviewedAt?
解决EF中TPH实体升级及变更追溯的问题
嘿,这个问题我太有共鸣了——刚接触EF的TPH(Table-Per-Hierarchy)继承时,确实容易被SQL里的表思维框住!结合你给出的模型,我来分享下实际项目里的解决方法:
一、EF中升级TPH实体的标准操作
首先明确:EF本身没有提供直接的“类型升级”API,但因为你的Info和Review共用一张表(TPH模式),我们可以直接操作数据库上下文的实体条目来实现:
核心思路
直接修改记录的鉴别器列(EF默认列名为Discriminator,如果没自定义的话),同时为ReviewedAt赋值,本质就是执行一条UPDATE语句。
代码示例
using (var context = new YourDbContext()) { // 查询到要升级的Info实例 var targetInfo = context.Infos.FirstOrDefault(i => i.Id == yourInfoId); if (targetInfo == null) return; // 获取实体的追踪条目 var entry = context.Entry(targetInfo); // 修改鉴别器值,将类型从Info切换为Review entry.Property("Discriminator").CurrentValue = "Review"; // 赋值ReviewedAt(用你准备好的时间) entry.Property("ReviewedAt").CurrentValue = DateTime.UtcNow; // 保存变更 context.SaveChanges(); }
注意事项
- 如果你自定义了鉴别器列名(比如用Fluent API配置过),要把
"Discriminator"改成你配置的名称; - 确保
ReviewedAt列在数据库中允许非空(因为你的Review类里标记了[Required]),升级时必须赋值; - 执行完变更后,后续查询这条记录时,EF会自动将它当作
Review实例返回。
二、变更追溯的最佳实践
如果需要追踪“从Info升级为Review”的历史,推荐这几种模式:
1. 审计日志表
创建一个独立的AuditLog实体,记录每次关键变更的细节:
public class AuditLog { public int Id { get; set; } public int EntityId { get; set; } // 关联被变更的Info/Review的Id public string EntityType { get; set; } // 比如"Info"或"Review" public string ChangeType { get; set; } // 比如"升级为Review" public DateTime ChangeTime { get; set; } public string ChangedBy { get; set; } // 操作人(如果有) public string ChangeDetails { get; set; } // 比如"Discriminator: Info → Review; ReviewedAt: 2024-05-20" }
然后通过EF的SaveChanges拦截器(或者重写SaveChanges方法),在保存前检查鉴别器的变更,自动写入审计日志。
2. 状态变更历史表
如果业务中还有其他状态流转,可单独创建StatusChangeHistory表,专门记录实体的类型/状态变更:
public class StatusChangeHistory { public int Id { get; set; } public int InfoId { get; set; } public string OldStatus { get; set; } // 比如"Info" public string NewStatus { get; set; } // 比如"Review" public DateTime ChangeTime { get; set; } public string Operator { get; set; } }
在执行升级操作时,手动插入一条历史记录,后续查询时就能清晰追溯变更轨迹。
3. 版本化实体
给Info基类添加版本字段:
public class Info { [Key] public int Id { get; set;} [Required] public DateTime PublishedAt { get; set;} public int Version { get; set; } // 每次变更自增 }
配合审计日志,每次升级时版本号+1,方便关联历史记录和当前实体的版本关系。
内容的提问来源于stack exchange,提问作者Yaugen Vlasau
相关产品推荐
相关产品推荐

