This commit is contained in:
2025-11-03 17:03:57 +08:00
commit 7a04b85667
16804 changed files with 2492292 additions and 0 deletions

View File

@@ -0,0 +1,259 @@
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;
}
}
}
}

View File

@@ -0,0 +1,266 @@
using Microsoft.EntityFrameworkCore;
using HardwarePerformance.Core.Entities;
namespace HardwarePerformance.Infrastructure.Data
{
public class DataSeeder
{
public static void SeedData(AppDbContext context)
{
// 确保数据库已创建
context.Database.EnsureCreated();
// 检查是否已有数据
if (context.Categories.Any())
{
return; // 数据库已有数据,不需要种子数据
}
// 添加初始产品类别
var categories = new List<Category>
{
new Category
{
Name = "手机CPU",
Description = "移动设备处理器性能排名"
},
new Category
{
Name = "手机GPU",
Description = "移动设备图形处理器性能排名"
},
new Category
{
Name = "电脑CPU",
Description = "桌面和笔记本处理器性能排名"
},
new Category
{
Name = "电脑GPU",
Description = "桌面和笔记本图形处理器性能排名"
}
};
context.Categories.AddRange(categories);
context.SaveChanges();
// 添加初始数据源
var dataSources = new List<DataSource>
{
new DataSource
{
Name = "Geekbench",
Description = "跨平台处理器和内存性能测试工具",
ApiUrl = "https://browser.geekbench.com/"
},
new DataSource
{
Name = "3DMark",
Description = "游戏和图形性能基准测试工具",
ApiUrl = "https://www.3dmark.com/"
},
new DataSource
{
Name = "AnTuTu",
Description = "移动设备综合性能测试平台",
ApiUrl = "https://www.antutu.com/"
}
};
context.DataSources.AddRange(dataSources);
context.SaveChanges();
// 添加一些示例产品数据
var mobileCpuCategory = context.Categories.FirstOrDefault(c => c.Name == "手机CPU");
var mobileGpuCategory = context.Categories.FirstOrDefault(c => c.Name == "手机GPU");
var desktopCpuCategory = context.Categories.FirstOrDefault(c => c.Name == "电脑CPU");
var desktopGpuCategory = context.Categories.FirstOrDefault(c => c.Name == "电脑GPU");
var geekbenchSource = context.DataSources.FirstOrDefault(s => s.Name == "Geekbench");
var threeDMarkSource = context.DataSources.FirstOrDefault(s => s.Name == "3DMark");
var antutuSource = context.DataSources.FirstOrDefault(s => s.Name == "AnTuTu");
if (mobileCpuCategory != null && geekbenchSource != null)
{
var mobileCpus = new List<Product>
{
new Product
{
Name = "Apple A17 Pro",
Model = "A17 Pro",
Manufacturer = "Apple",
ReleaseDate = new DateTime(2023, 9, 1),
ImageUrl = "/images/apple-a17-pro.jpg",
CategoryId = mobileCpuCategory.Id,
CurrentRank = 1
},
new Product
{
Name = "Snapdragon 8 Gen 3",
Model = "SM8650-AB",
Manufacturer = "Qualcomm",
ReleaseDate = new DateTime(2023, 10, 1),
ImageUrl = "/images/snapdragon-8-gen-3.jpg",
CategoryId = mobileCpuCategory.Id,
CurrentRank = 2
},
new Product
{
Name = "MediaTek Dimensity 9300",
Model = "MT6989",
Manufacturer = "MediaTek",
ReleaseDate = new DateTime(2023, 11, 1),
ImageUrl = "/images/dimensity-9300.jpg",
CategoryId = mobileCpuCategory.Id,
CurrentRank = 3
}
};
context.Products.AddRange(mobileCpus);
context.SaveChanges();
// 添加性能分数
var performanceScores = new List<PerformanceScore>();
foreach (var cpu in mobileCpus)
{
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Single-Core",
Score = cpu.Name.Contains("A17") ? 2950 : cpu.Name.Contains("Snapdragon") ? 2300 : 2200,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
});
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Multi-Core",
Score = cpu.Name.Contains("A17") ? 7200 : cpu.Name.Contains("Snapdragon") ? 7400 : 7500,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
});
}
context.PerformanceScores.AddRange(performanceScores);
context.SaveChanges();
// 添加规格参数
var specifications = new List<Specification>();
foreach (var cpu in mobileCpus)
{
if (cpu.Name.Contains("A17"))
{
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Value = "3nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Value = "6",
Unit = "核"
});
}
else if (cpu.Name.Contains("Snapdragon"))
{
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Value = "4nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Value = "8",
Unit = "核"
});
}
else if (cpu.Name.Contains("Dimensity"))
{
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "制程工艺",
Value = "4nm",
Unit = "nm"
});
specifications.Add(new Specification
{
ProductId = cpu.Id,
Key = "核心数",
Value = "8",
Unit = "核"
});
}
}
context.Specifications.AddRange(specifications);
context.SaveChanges();
}
if (desktopCpuCategory != null && geekbenchSource != null)
{
var desktopCpus = new List<Product>
{
new Product
{
Name = "Intel Core i9-14900K",
Model = "i9-14900K",
Manufacturer = "Intel",
ReleaseDate = new DateTime(2023, 10, 1),
ImageUrl = "/images/intel-i9-14900k.jpg",
CategoryId = desktopCpuCategory.Id,
CurrentRank = 1
},
new Product
{
Name = "AMD Ryzen 9 7950X",
Model = "Ryzen 9 7950X",
Manufacturer = "AMD",
ReleaseDate = new DateTime(2023, 9, 1),
ImageUrl = "/images/amd-ryzen9-7950x.jpg",
CategoryId = desktopCpuCategory.Id,
CurrentRank = 2
}
};
context.Products.AddRange(desktopCpus);
context.SaveChanges();
// 添加性能分数
var performanceScores = new List<PerformanceScore>();
foreach (var cpu in desktopCpus)
{
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Single-Core",
Score = cpu.Name.Contains("Intel") ? 3200 : 2300,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
});
performanceScores.Add(new PerformanceScore
{
ProductId = cpu.Id,
BenchmarkType = "Multi-Core",
Score = cpu.Name.Contains("Intel") ? 22000 : 30000,
TestDate = DateTime.Now,
DataSourceId = geekbenchSource.Id
});
}
context.PerformanceScores.AddRange(performanceScores);
context.SaveChanges();
}
}
}
}

View File

@@ -0,0 +1,226 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace HardwarePerformance.Infrastructure.Data.Migrations
{
/// <inheritdoc />
public partial class InitialCreate : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Categories",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Categories", x => x.Id);
});
migrationBuilder.CreateTable(
name: "DataSources",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Description = table.Column<string>(type: "text", nullable: true),
ApiUrl = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DataSources", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
Name = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: false),
Model = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Manufacturer = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
ReleaseDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
ImageUrl = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true),
CategoryId = table.Column<int>(type: "int", nullable: false),
CurrentRank = table.Column<int>(type: "int", nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
table.ForeignKey(
name: "FK_Products_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "PerformanceScores",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
BenchmarkType = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: false),
Score = table.Column<decimal>(type: "decimal(10,2)", nullable: false),
TestDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
DataSourceId = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_PerformanceScores", x => x.Id);
table.ForeignKey(
name: "FK_PerformanceScores_DataSources_DataSourceId",
column: x => x.DataSourceId,
principalTable: "DataSources",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_PerformanceScores_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RankingHistories",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
Rank = table.Column<int>(type: "int", nullable: false),
CategoryId = table.Column<int>(type: "int", nullable: false),
RecordDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RankingHistories", x => x.Id);
table.ForeignKey(
name: "FK_RankingHistories_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RankingHistories_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Specifications",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
ProductId = table.Column<int>(type: "int", nullable: false),
Key = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false),
Value = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: false),
Unit = table.Column<string>(type: "varchar(50)", maxLength: 50, nullable: true),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
UpdatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Specifications", x => x.Id);
table.ForeignKey(
name: "FK_Specifications_Products_ProductId",
column: x => x.ProductId,
principalTable: "Products",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_PerformanceScores_BenchmarkType",
table: "PerformanceScores",
column: "BenchmarkType");
migrationBuilder.CreateIndex(
name: "IX_PerformanceScores_ProductId",
table: "PerformanceScores",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Products_CategoryId",
table: "Products",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_Products_Manufacturer",
table: "Products",
column: "Manufacturer");
migrationBuilder.CreateIndex(
name: "IX_Products_Model",
table: "Products",
column: "Model");
migrationBuilder.CreateIndex(
name: "IX_Products_Name",
table: "Products",
column: "Name");
migrationBuilder.CreateIndex(
name: "IX_RankingHistories_CategoryId",
table: "RankingHistories",
column: "CategoryId");
migrationBuilder.CreateIndex(
name: "IX_RankingHistories_ProductId",
table: "RankingHistories",
column: "ProductId");
migrationBuilder.CreateIndex(
name: "IX_Specifications_ProductId",
table: "Specifications",
column: "ProductId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "PerformanceScores");
migrationBuilder.DropTable(
name: "RankingHistories");
migrationBuilder.DropTable(
name: "Specifications");
migrationBuilder.DropTable(
name: "DataSources");
migrationBuilder.DropTable(
name: "Products");
migrationBuilder.DropTable(
name: "Categories");
}
}
}

View File

@@ -0,0 +1,315 @@
// <auto-generated />
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using HardwarePerformance.Infrastructure.Data;
#nullable disable
namespace HardwarePerformance.Infrastructure.Data.Migrations
{
[DbContext(typeof(AppDbContext))]
partial class AppDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "9.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
MySqlModelBuilderExtensions.UseCollation(modelBuilder, "utf8mb4_0900_ai_ci");
modelBuilder.Entity("HardwarePerformance.Core.Entities.Category", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("Categories");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.DataSource", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("ApiUrl")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Description")
.HasColumnType("text");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.ToTable("DataSources");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.PerformanceScore", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<string>("BenchmarkType")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("DataSourceId")
.HasColumnType("int");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<decimal>("Score")
.HasColumnType("decimal(10,2)");
b.Property<DateTime>("TestDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("BenchmarkType");
b.HasIndex("ProductId");
b.ToTable("PerformanceScores");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CategoryId")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("ImageUrl")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<string>("Manufacturer")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Model")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("CurrentRank")
.HasColumnType("int");
b.Property<DateTime>("ReleaseDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("Manufacturer");
b.HasIndex("Model");
b.HasIndex("Name");
b.ToTable("Products");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.RankingHistory", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<int>("CategoryId")
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<int>("Rank")
.HasColumnType("int");
b.Property<DateTime>("RecordDate")
.HasColumnType("datetime(6)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("CategoryId");
b.HasIndex("ProductId");
b.ToTable("RankingHistories");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Specification", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<string>("Key")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int>("ProductId")
.HasColumnType("int");
b.Property<string>("Unit")
.HasMaxLength(50)
.HasColumnType("varchar(50)");
b.Property<string>("Value")
.IsRequired()
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<DateTime>("UpdatedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("ProductId");
b.ToTable("Specifications");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.PerformanceScore", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.DataSource", "DataSource")
.WithMany()
.HasForeignKey("DataSourceId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("PerformanceScores")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("DataSource");
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Category", "Category")
.WithMany("Products")
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.RankingHistory", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Category", "Category")
.WithMany()
.HasForeignKey("CategoryId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("RankingHistories")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Category");
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Specification", b =>
{
b.HasOne("HardwarePerformance.Core.Entities.Product", "Product")
.WithMany("Specifications")
.HasForeignKey("ProductId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Product");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Category", b =>
{
b.Navigation("Products");
});
modelBuilder.Entity("HardwarePerformance.Core.Entities.Product", b =>
{
b.Navigation("PerformanceScores");
b.Navigation("RankingHistories");
b.Navigation("Specifications");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,205 @@
using System.Data;
using MySql.Data.MySqlClient;
using HardwarePerformance.Core.Entities;
namespace HardwarePerformance.Infrastructure.Data;
public class SimpleAppDbContext
{
private readonly string _connectionString;
public SimpleAppDbContext(IConfiguration configuration)
{
_connectionString = configuration.GetConnectionString("DefaultConnection");
}
public async Task<bool> TestConnectionAsync()
{
try
{
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
return connection.State == ConnectionState.Open;
}
catch
{
return false;
}
}
public async Task InitializeDatabaseAsync()
{
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
// 创建Categories表
var createCategoriesTable = @"
CREATE TABLE IF NOT EXISTS Categories (
Id INT AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
Description TEXT,
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
)";
using var cmd = new MySqlCommand(createCategoriesTable, connection);
await cmd.ExecuteNonQueryAsync();
// 创建Products表
var createProductsTable = @"
CREATE TABLE IF NOT EXISTS Products (
Id INT AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(200) NOT NULL,
Model VARCHAR(100),
Manufacturer VARCHAR(100),
ImageUrl VARCHAR(500),
ReleaseDate DATE,
CategoryId INT,
CurrentRank INT,
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (CategoryId) REFERENCES Categories(Id)
)";
cmd.CommandText = createProductsTable;
await cmd.ExecuteNonQueryAsync();
// 创建PerformanceScores表
var createPerformanceScoresTable = @"
CREATE TABLE IF NOT EXISTS PerformanceScores (
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL,
BenchmarkType VARCHAR(50) NOT NULL,
Score INT NOT NULL,
TestDate DATETIME DEFAULT CURRENT_TIMESTAMP,
DataSourceId INT,
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)";
cmd.CommandText = createPerformanceScoresTable;
await cmd.ExecuteNonQueryAsync();
// 创建DataSources表
var createDataSourcesTable = @"
CREATE TABLE IF NOT EXISTS DataSources (
Id INT AUTO_INCREMENT PRIMARY KEY,
Name VARCHAR(100) NOT NULL,
Description TEXT,
WebsiteUrl VARCHAR(500),
CreatedAt DATETIME DEFAULT CURRENT_TIMESTAMP
)";
cmd.CommandText = createDataSourcesTable;
await cmd.ExecuteNonQueryAsync();
// 创建Specifications表
var createSpecificationsTable = @"
CREATE TABLE IF NOT EXISTS Specifications (
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL,
Name VARCHAR(100) NOT NULL,
Value TEXT NOT NULL,
Unit VARCHAR(50),
FOREIGN KEY (ProductId) REFERENCES Products(Id)
)";
cmd.CommandText = createSpecificationsTable;
await cmd.ExecuteNonQueryAsync();
// 创建RankingHistories表
var createRankingHistoriesTable = @"
CREATE TABLE IF NOT EXISTS RankingHistories (
Id INT AUTO_INCREMENT PRIMARY KEY,
ProductId INT NOT NULL,
Rank INT NOT NULL,
CategoryId INT NOT NULL,
RecordedAt DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (ProductId) REFERENCES Products(Id),
FOREIGN KEY (CategoryId) REFERENCES Categories(Id)
)";
cmd.CommandText = createRankingHistoriesTable;
await cmd.ExecuteNonQueryAsync();
}
public async Task SeedInitialDataAsync()
{
using var connection = new MySqlConnection(_connectionString);
await connection.OpenAsync();
// 检查是否已有数据
var checkCategoriesCmd = new MySqlCommand("SELECT COUNT(*) FROM Categories", connection);
var categoryCount = Convert.ToInt32(await checkCategoriesCmd.ExecuteScalarAsync());
if (categoryCount > 0)
{
return; // 已有数据,不需要种子数据
}
// 插入Categories
var insertCategories = @"
INSERT INTO Categories (Name, Description) VALUES
('手机CPU', '移动设备处理器'),
('手机GPU', '移动设备图形处理器'),
('电脑CPU', '桌面和笔记本处理器'),
('电脑GPU', '桌面和笔记本图形处理器')";
using var cmd = new MySqlCommand(insertCategories, connection);
await cmd.ExecuteNonQueryAsync();
// 插入DataSources
var insertDataSources = @"
INSERT INTO DataSources (Name, Description, WebsiteUrl) VALUES
('Geekbench', '处理器和内存性能测试', 'https://www.geekbench.com'),
('3DMark', '图形和游戏性能测试', 'https://www.3dmark.com'),
('AnTuTu', '移动设备综合性能测试', 'https://www.antutu.com')";
cmd.CommandText = insertDataSources;
await cmd.ExecuteNonQueryAsync();
// 插入示例产品
var insertProducts = @"
INSERT INTO Products (Name, Model, Manufacturer, ReleaseDate, CategoryId, CurrentRank) VALUES
('Apple A17 Pro', 'A17 Pro', 'Apple', '2023-09-12', 1, 1),
('Snapdragon 8 Gen 3', 'SM8650-AB', 'Qualcomm', '2023-10-24', 1, 2),
('Intel Core i9-13900K', 'Core i9-13900K', 'Intel', '2022-10-20', 3, 1),
('AMD Ryzen 9 7950X', 'Ryzen 9 7950X', 'AMD', '2022-09-27', 3, 2),
('NVIDIA GeForce RTX 4090', 'RTX 4090', 'NVIDIA', '2022-10-12', 4, 1),
('AMD Radeon RX 7900 XTX', 'RX 7900 XTX', 'AMD', '2022-12-13', 4, 2)";
cmd.CommandText = insertProducts;
await cmd.ExecuteNonQueryAsync();
// 插入性能分数
var insertPerformanceScores = @"
INSERT INTO PerformanceScores (ProductId, BenchmarkType, Score, DataSourceId) VALUES
(1, 'Geekbench Single-Core', 2900, 1),
(1, 'Geekbench Multi-Core', 7200, 1),
(2, 'Geekbench Single-Core', 2300, 1),
(2, 'Geekbench Multi-Core', 7400, 1),
(3, 'Geekbench Single-Core', 3200, 1),
(3, 'Geekbench Multi-Core', 24000, 1),
(4, 'Geekbench Single-Core', 2600, 1),
(4, 'Geekbench Multi-Core', 26000, 1)";
cmd.CommandText = insertPerformanceScores;
await cmd.ExecuteNonQueryAsync();
// 插入规格参数
var insertSpecifications = @"
INSERT INTO Specifications (ProductId, Name, Value, Unit) VALUES
(1, '工艺', '3nm', null),
(1, '核心数', '6', '个'),
(1, '线程数', '6', '个'),
(2, '工艺', '4nm', null),
(2, '核心数', '8', '个'),
(2, '线程数', '8', '个'),
(3, '工艺', 'Intel 7', null),
(3, '核心数', '24', '个'),
(3, '线程数', '32', '个'),
(4, '工艺', '5nm', null),
(4, '核心数', '16', '个'),
(4, '线程数', '32', '个')";
cmd.CommandText = insertSpecifications;
await cmd.ExecuteNonQueryAsync();
}
}