Files
it/backend/HardwarePerformance.Infrastructure/Data/AppDbContext.cs
2025-11-03 17:03:57 +08:00

259 lines
9.1 KiB
C#

using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Core.Entities;
namespace HardwarePerformance.Infrastructure.Data
{
/// <summary>
/// 基础实体类
/// </summary>
public abstract class BaseEntity
{
public DateTime CreatedAt { get; set; }
public DateTime UpdatedAt { get; set; }
}
/// <summary>
/// 应用程序数据库上下文
/// </summary>
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
// DbSets
public DbSet<Category> Categories { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<PerformanceScore> PerformanceScores { get; set; }
public DbSet<Specification> Specifications { get; set; }
public DbSet<DataSource> DataSources { get; set; }
public DbSet<RankingHistory> RankingHistories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// 配置Category实体
modelBuilder.Entity<Category>(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<Product>(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<PerformanceScore>(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<Specification>(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<DataSource>(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<RankingHistory>(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<int> 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;
}
}
}
}