如何在填充Post实体种子数据时自动计算并保存Rate字段值?
解决方案
首先你当前的Rate属性setter逻辑存在问题:它完全忽略传入的value参数,强制用TotalRate/RateCount赋值,而且未处理RateCount=0时的除法异常。要实现种子数据填充时自动计算并保存Rate,可以参考以下几种方案:
方案1:将Rate改为只读计算属性,结合ORM配置或保存前手动计算
如果希望Rate始终是TotalRate和RateCount的实时计算结果,可将其改为只读计算属性,再根据所用ORM(比如Entity Framework)的特性配置是否存储到数据库:
public class Post { public int Id { get; set; } public int ViewCount { get; set; } public int RateCount { get; set; } public int TotalRate { get; set; } // 只读计算属性,实时计算Rate,处理除数为0的情况 public decimal Rate { get { return RateCount == 0 ? 0 : (decimal)TotalRate / RateCount; } } }
若需将Rate保存到数据库:
- 用Entity Framework Core的话,可在
OnModelCreating中配置该属性为数据库计算列,由数据库自动维护值:
此时种子数据只需填充protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Post>() .Property(p => p.Rate) .HasComputedColumnSql("CAST(TotalRate AS DECIMAL)/RateCount"); }TotalRate和RateCount,Rate会由数据库自动计算并存储。 - 若不用数据库计算列,可在种子数据填充后、保存前手动遍历计算:
var seedPosts = new List<Post> { new Post { ViewCount = 100, RateCount = 5, TotalRate = 20 }, // 其他种子数据 }; // 计算属性无需手动赋值,直接保存即可 context.Posts.AddRange(seedPosts); context.SaveChanges();
方案2:修正实体类逻辑,让TotalRate/RateCount变化时自动更新Rate
如果需要保留Rate的可存储属性,可修改实体类,在TotalRate或RateCount变更时自动触发计算:
public class Post { public int Id { get; set; } public int ViewCount { get; set; } private int _rateCount; public int RateCount { get => _rateCount; set { _rateCount = value; CalculateRate(); } } private int _totalRate; public int TotalRate { get => _totalRate; set { _totalRate = value; CalculateRate(); } } public decimal Rate { get; private set; } // 统一计算逻辑 private void CalculateRate() { Rate = RateCount == 0 ? 0 : (decimal)TotalRate / RateCount; } // 带参数构造函数,填充种子数据时直接传入计算所需值 public Post(int totalRate, int rateCount) { _totalRate = totalRate; _rateCount = rateCount; CalculateRate(); } // EF需要无参构造函数 public Post(){} }
填充种子数据时,只需传入TotalRate和RateCount,Rate会自动计算:
var seedPost = new Post(20, 5); // 自动计算Rate为4.0 context.Posts.Add(seedPost); context.SaveChanges();
方案3:利用ORM的保存前钩子统一计算
不管Rate的属性逻辑如何,都可以在ORM的保存前事件中统一计算Rate。比如在Entity Framework Core中重写DbContext的SaveChanges方法:
public class YourDbContext : DbContext { // 配置DbSet等内容 public override int SaveChanges() { CalculatePostRates(); return base.SaveChanges(); } public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { CalculatePostRates(); return base.SaveChangesAsync(cancellationToken); } private void CalculatePostRates() { // 筛选新增或修改的Post实体 var postEntries = ChangeTracker.Entries<Post>() .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified); foreach(var entry in postEntries) { var post = entry.Entity; post.Rate = post.RateCount == 0 ? 0 : (decimal)post.TotalRate / post.RateCount; } } }
这种方式无需修改实体类逻辑,不管是种子数据填充还是日常数据修改,只要执行保存操作,Rate都会自动计算并保存。
内容的提问来源于stack exchange,提问作者sos.call.112
相关产品推荐
相关产品推荐

