using Microsoft.EntityFrameworkCore; using HardwarePerformance.Core.Entities; namespace HardwarePerformance.Infrastructure.Data { /// /// 应用程序数据库上下文 /// public class AppDbContext : DbContext { public AppDbContext(DbContextOptions options) : base(options) { } // DbSets public DbSet Categories { get; set; } public DbSet Products { get; set; } public DbSet PerformanceScores { get; set; } public DbSet Specifications { get; set; } public DbSet DataSources { get; set; } public DbSet RankingHistories { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 配置Category实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Name) .IsRequired() .HasMaxLength(100); entity.Property(e => e.Description) .HasMaxLength(500); entity.Property(e => e.IconUrl) .HasMaxLength(500); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); entity.Property(e => e.UpdatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); entity.HasIndex(e => e.Name).IsUnique(); entity.HasIndex(e => e.SortOrder); }); // 配置Product实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Name) .IsRequired() .HasMaxLength(200); entity.Property(e => e.Model) .IsRequired() .HasMaxLength(200); entity.Property(e => e.Manufacturer) .IsRequired() .HasMaxLength(100); entity.Property(e => e.ImageUrl) .HasMaxLength(500); entity.Property(e => e.Description) .HasMaxLength(2000); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); entity.Property(e => e.UpdatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); // 配置外键关系 entity.HasOne(e => e.Category) .WithMany(c => c.Products) .HasForeignKey(e => e.CategoryId) .OnDelete(DeleteBehavior.Cascade); // 配置索引 entity.HasIndex(e => e.Name); entity.HasIndex(e => e.Model); entity.HasIndex(e => e.CategoryId); entity.HasIndex(e => e.PerformanceScore); entity.HasIndex(e => e.CurrentRank); entity.HasIndex(e => e.Manufacturer); entity.HasIndex(e => e.ReleaseYear); entity.HasIndex(e => new { e.CategoryId, e.CurrentRank }); }); // 配置PerformanceScore实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.TestName) .IsRequired() .HasMaxLength(100); entity.Property(e => e.Unit) .HasMaxLength(20); entity.Property(e => e.TestVersion) .HasMaxLength(50); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); // 配置外键关系 entity.HasOne(e => e.Product) .WithMany(p => p.PerformanceScores) .HasForeignKey(e => e.ProductId) .OnDelete(DeleteBehavior.Cascade); entity.HasOne(e => e.DataSource) .WithMany(d => d.PerformanceScores) .HasForeignKey(e => e.DataSourceId) .OnDelete(DeleteBehavior.Restrict); // 配置索引 entity.HasIndex(e => new { e.ProductId, e.TestName }); entity.HasIndex(e => e.Score); entity.HasIndex(e => e.TestDate); }); // 配置Specification实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.GroupName) .IsRequired() .HasMaxLength(100); entity.Property(e => e.Name) .IsRequired() .HasMaxLength(100); entity.Property(e => e.Value) .IsRequired() .HasMaxLength(500); entity.Property(e => e.Unit) .HasMaxLength(20); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); entity.Property(e => e.UpdatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); // 配置外键关系 entity.HasOne(e => e.Product) .WithMany(p => p.Specifications) .HasForeignKey(e => e.ProductId) .OnDelete(DeleteBehavior.Cascade); // 配置索引 entity.HasIndex(e => new { e.ProductId, e.GroupName }); entity.HasIndex(e => new { e.ProductId, e.Name }); entity.HasIndex(e => e.IsKeySpecification); }); // 配置DataSource实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.Name) .IsRequired() .HasMaxLength(100); entity.Property(e => e.Description) .HasMaxLength(500); entity.Property(e => e.Url) .HasMaxLength(500); entity.Property(e => e.Type) .IsRequired() .HasMaxLength(50); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); entity.Property(e => e.UpdatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); // 配置索引 entity.HasIndex(e => e.Name).IsUnique(); entity.HasIndex(e => e.Type); }); // 配置RankingHistory实体 modelBuilder.Entity(entity => { entity.HasKey(e => e.Id); entity.Property(e => e.CreatedAt) .HasDefaultValueSql("UTC_TIMESTAMP()"); // 配置外键关系 entity.HasOne(e => e.Product) .WithMany(p => p.RankingHistories) .HasForeignKey(e => e.ProductId) .OnDelete(DeleteBehavior.Cascade); // 配置索引 entity.HasIndex(e => new { e.ProductId, e.RecordDate }); entity.HasIndex(e => e.Rank); entity.HasIndex(e => e.RecordDate); }); } public override int SaveChanges() { UpdateTimestamps(); return base.SaveChanges(); } public override Task SaveChangesAsync(CancellationToken cancellationToken = default) { UpdateTimestamps(); return base.SaveChangesAsync(cancellationToken); } private void UpdateTimestamps() { var entries = ChangeTracker.Entries() .Where(e => e.Entity is BaseEntity && (e.State == EntityState.Added || e.State == EntityState.Modified)); foreach (var entry in entries) { if (entry.State == EntityState.Added) { ((BaseEntity)entry.Entity).CreatedAt = DateTime.UtcNow; } ((BaseEntity)entry.Entity).UpdatedAt = DateTime.UtcNow; } } } }