EF Core 8中如何通过实体拆分实现RuleApp多版本存储?
实现EF Core 8下的RuleApp版本控制(一对多关联)
1. 定义实体类
先创建两个实体类,分别对应存储唯一规则应用的主表,以及存储版本快照的版本表:
RuleApp 实体(主表)
public class RuleApp { public int Id { get; set; } // 唯一名称,添加唯一约束确保只保存一次 public string Name { get; set; } = string.Empty; // 导航属性:一个RuleApp对应多个版本 public ICollection<RuleAppRevision> Revisions { get; set; } = new List<RuleAppRevision>(); }
RuleAppRevision 实体(版本表)
public class RuleAppRevision { public int Id { get; set; } // 外键:关联到所属的RuleApp public int RuleAppId { get; set; } // 版本标识,可自定义规则(如v1、20240520-001) public string VersionNumber { get; set; } = string.Empty; // 版本创建时间 public DateTime CreatedAt { get; set; } = DateTime.UtcNow; // 序列化存储的JSON属性 public string Rules { get; set; } = string.Empty; public string Entities { get; set; } = string.Empty; public string DataElements { get; set; } = string.Empty; // 导航属性:关联到对应的RuleApp public RuleApp RuleApp { get; set; } = null!; }
2. DbContext 配置
在你的DbContext子类中,通过Fluent API配置一对多关联、唯一约束和JSON列映射:
public class YourDbContext : DbContext { public DbSet<RuleApp> RuleApps { get; set; } public DbSet<RuleAppRevision> RuleAppRevisions { get; set; } public YourDbContext(DbContextOptions<YourDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置RuleApp名称的唯一约束 modelBuilder.Entity<RuleApp>() .HasIndex(r => r.Name) .IsUnique(); // 配置一对多关联:RuleApp包含多个Revision,Revision属于单个RuleApp modelBuilder.Entity<RuleApp>() .HasMany(r => r.Revisions) .WithOne(r => r.RuleApp) .HasForeignKey(r => r.RuleAppId) .OnDelete(DeleteBehavior.Cascade); // 删除RuleApp时自动删除所有版本,可根据需求调整为Restrict // 配置JSON列(SQL Server用nvarchar(max),PostgreSQL可改为jsonb) modelBuilder.Entity<RuleAppRevision>() .Property(r => r.Rules) .HasColumnType("nvarchar(max)"); modelBuilder.Entity<RuleAppRevision>() .Property(r => r.Entities) .HasColumnType("nvarchar(max)"); modelBuilder.Entity<RuleAppRevision>() .Property(r => r.DataElements) .HasColumnType("nvarchar(max)"); // 可选:用HasConversion实现强类型与JSON的自动序列化/反序列化 // 假设你有RulesModel强类型类,示例配置: // modelBuilder.Entity<RuleAppRevision>() // .Property(r => r.Rules) // .HasConversion( // v => JsonSerializer.Serialize(v, new JsonSerializerOptions { WriteIndented = true }), // v => JsonSerializer.Deserialize<RulesModel>(v, new JsonSerializerOptions { WriteIndented = true })!) // .HasColumnType("nvarchar(max)"); } }
3. 创建新版本的逻辑
当用户需要基于某个版本修改并生成新版本时,直接复制源版本的JSON属性,创建新的RuleAppRevision实例并关联到同一个RuleApp即可:
public async Task CreateNewRevisionAsync(int ruleAppId, int sourceRevisionId, string newVersionNumber) { using var context = new YourDbContext(_options); var sourceRevision = await context.RuleAppRevisions .FirstOrDefaultAsync(r => r.Id == sourceRevisionId && r.RuleAppId == ruleAppId); if (sourceRevision == null) throw new InvalidOperationException("指定的源版本不存在"); var newRevision = new RuleAppRevision { RuleAppId = ruleAppId, VersionNumber = newVersionNumber, Rules = sourceRevision.Rules, Entities = sourceRevision.Entities, DataElements = sourceRevision.DataElements, CreatedAt = DateTime.UtcNow }; context.RuleAppRevisions.Add(newRevision); await context.SaveChangesAsync(); }
补充说明
- 版本号唯一性:可给
RuleAppRevision的VersionNumber和RuleAppId添加联合唯一索引,确保同一RuleApp下版本号不重复。 - JSON列优化:如果使用PostgreSQL,建议用
jsonb类型,支持索引和更高效的查询;SQL Server可考虑开启JSON索引提升查询性能。
内容的提问来源于stack exchange,提问作者Furqan Safdar
相关产品推荐
相关产品推荐

