This commit is contained in:
2026-07-24 13:11:09 +08:00 Unverified
parent 6c3021ea8d
commit 30d793773c
23 changed files with 3479 additions and 79 deletions
@@ -0,0 +1,169 @@
using Microsoft.EntityFrameworkCore;
namespace Jiaowu.Api.Infrastructure.Persistence;
public sealed class DevelopmentSqliteMigrator(
AppDbContext db,
ILogger<DevelopmentSqliteMigrator> logger)
{
private const string PeopleAndCoursesMigration = "20260724_01_people_courses";
public async Task MigrateAsync(CancellationToken cancellationToken = default)
{
if (!db.Database.IsSqlite())
{
return;
}
await db.Database.ExecuteSqlRawAsync(
"""
CREATE TABLE IF NOT EXISTS "__DevelopmentSchemaHistory" (
"MigrationId" TEXT NOT NULL CONSTRAINT "PK___DevelopmentSchemaHistory" PRIMARY KEY,
"AppliedAt" TEXT NOT NULL
);
""",
cancellationToken);
var applied = await db.Database
.SqlQuery<string>(
$"""
SELECT "MigrationId" AS "Value"
FROM "__DevelopmentSchemaHistory"
WHERE "MigrationId" = {PeopleAndCoursesMigration}
""")
.AnyAsync(cancellationToken);
if (applied)
{
return;
}
await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
foreach (var statement in PeopleAndCoursesStatements)
{
await db.Database.ExecuteSqlRawAsync(statement, cancellationToken);
}
await db.Database.ExecuteSqlInterpolatedAsync(
$"""
INSERT INTO "__DevelopmentSchemaHistory" ("MigrationId", "AppliedAt")
VALUES ({PeopleAndCoursesMigration}, {DateTime.UtcNow});
""",
cancellationToken);
await transaction.CommitAsync(cancellationToken);
logger.LogInformation(
"Applied SQLite development schema migration {MigrationId}.",
PeopleAndCoursesMigration);
}
private static readonly string[] PeopleAndCoursesStatements =
[
"""
CREATE TABLE IF NOT EXISTS "Teachers" (
"Id" TEXT NOT NULL CONSTRAINT "PK_Teachers" PRIMARY KEY,
"TeacherNumber" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"Gender" INTEGER NOT NULL,
"CollegeId" TEXT NOT NULL,
"Title" TEXT NULL,
"Status" INTEGER NOT NULL,
"HireDate" TEXT NULL,
"IsExternal" INTEGER NOT NULL,
"Phone" TEXT NULL,
"Email" TEXT NULL,
"Notes" TEXT NULL,
"UserId" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_Teachers_Colleges_CollegeId"
FOREIGN KEY ("CollegeId") REFERENCES "Colleges" ("Id") ON DELETE RESTRICT,
CONSTRAINT "FK_Teachers_AspNetUsers_UserId"
FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE SET NULL
);
""",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_Teachers_TeacherNumber"
ON "Teachers" ("TeacherNumber");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Teachers_CollegeId_Status"
ON "Teachers" ("CollegeId", "Status");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Teachers_UserId"
ON "Teachers" ("UserId");
""",
"""
CREATE TABLE IF NOT EXISTS "Students" (
"Id" TEXT NOT NULL CONSTRAINT "PK_Students" PRIMARY KEY,
"StudentNumber" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"Gender" INTEGER NOT NULL,
"AdministrativeClassId" TEXT NOT NULL,
"EnrollmentYear" INTEGER NOT NULL,
"EnrollmentDate" TEXT NOT NULL,
"Status" INTEGER NOT NULL,
"DateOfBirth" TEXT NULL,
"Phone" TEXT NULL,
"Email" TEXT NULL,
"Notes" TEXT NULL,
"UserId" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
CONSTRAINT "FK_Students_AdministrativeClasses_AdministrativeClassId"
FOREIGN KEY ("AdministrativeClassId") REFERENCES "AdministrativeClasses" ("Id")
ON DELETE RESTRICT,
CONSTRAINT "FK_Students_AspNetUsers_UserId"
FOREIGN KEY ("UserId") REFERENCES "AspNetUsers" ("Id") ON DELETE SET NULL
);
""",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_Students_StudentNumber"
ON "Students" ("StudentNumber");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Students_AdministrativeClassId_Status"
ON "Students" ("AdministrativeClassId", "Status");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Students_EnrollmentYear"
ON "Students" ("EnrollmentYear");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Students_UserId"
ON "Students" ("UserId");
""",
"""
CREATE TABLE IF NOT EXISTS "Courses" (
"Id" TEXT NOT NULL CONSTRAINT "PK_Courses" PRIMARY KEY,
"CollegeId" TEXT NOT NULL,
"EnglishName" TEXT NULL,
"Credits" TEXT NOT NULL,
"TotalHours" INTEGER NOT NULL,
"LectureHours" INTEGER NOT NULL,
"PracticeHours" INTEGER NOT NULL,
"Nature" INTEGER NOT NULL,
"AssessmentMethod" INTEGER NOT NULL,
"Description" TEXT NULL,
"CreatedAt" TEXT NOT NULL,
"UpdatedAt" TEXT NOT NULL,
"Code" TEXT NOT NULL,
"Name" TEXT NOT NULL,
"SortOrder" INTEGER NOT NULL,
"IsEnabled" INTEGER NOT NULL,
CONSTRAINT "FK_Courses_Colleges_CollegeId"
FOREIGN KEY ("CollegeId") REFERENCES "Colleges" ("Id") ON DELETE RESTRICT
);
""",
"""
CREATE UNIQUE INDEX IF NOT EXISTS "IX_Courses_Code" ON "Courses" ("Code");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Courses_IsEnabled_SortOrder"
ON "Courses" ("IsEnabled", "SortOrder");
""",
"""
CREATE INDEX IF NOT EXISTS "IX_Courses_CollegeId_Nature"
ON "Courses" ("CollegeId", "Nature");
"""
];
}