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;
}
}
}
}