培养方案:专业/年级版本、课程模块、学分校验、复制版本、发布锁定、旧版本归档。
教学任务:学期开课、授课教师、唯一主讲、合班、容量与周次校验、发布及结课。 SQLite 开发库已自动升级,无需删除原数据库。 新增对应 MySQL EF Core 迁移。 Vue 已编译进 wwwroot,仍可只运行 ASP.NET Core 单服务。 桌面端及 390px 窄屏页面验证通过,无前端控制台错误。
This commit is contained in:
@@ -7,6 +7,8 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
ILogger<DevelopmentSqliteMigrator> logger)
|
||||
{
|
||||
private const string PeopleAndCoursesMigration = "20260724_01_people_courses";
|
||||
private const string CurriculumPlansMigration = "20260724_02_curriculum_plans";
|
||||
private const string TeachingTasksMigration = "20260724_03_teaching_tasks";
|
||||
|
||||
public async Task MigrateAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -24,12 +26,31 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
""",
|
||||
cancellationToken);
|
||||
|
||||
await ApplyMigrationAsync(
|
||||
PeopleAndCoursesMigration,
|
||||
PeopleAndCoursesStatements,
|
||||
cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
CurriculumPlansMigration,
|
||||
CurriculumPlansStatements,
|
||||
cancellationToken);
|
||||
await ApplyMigrationAsync(
|
||||
TeachingTasksMigration,
|
||||
TeachingTasksStatements,
|
||||
cancellationToken);
|
||||
}
|
||||
|
||||
private async Task ApplyMigrationAsync(
|
||||
string migrationId,
|
||||
IEnumerable<string> statements,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var applied = await db.Database
|
||||
.SqlQuery<string>(
|
||||
$"""
|
||||
SELECT "MigrationId" AS "Value"
|
||||
FROM "__DevelopmentSchemaHistory"
|
||||
WHERE "MigrationId" = {PeopleAndCoursesMigration}
|
||||
WHERE "MigrationId" = {migrationId}
|
||||
""")
|
||||
.AnyAsync(cancellationToken);
|
||||
if (applied)
|
||||
@@ -38,7 +59,7 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
}
|
||||
|
||||
await using var transaction = await db.Database.BeginTransactionAsync(cancellationToken);
|
||||
foreach (var statement in PeopleAndCoursesStatements)
|
||||
foreach (var statement in statements)
|
||||
{
|
||||
await db.Database.ExecuteSqlRawAsync(statement, cancellationToken);
|
||||
}
|
||||
@@ -46,13 +67,13 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
await db.Database.ExecuteSqlInterpolatedAsync(
|
||||
$"""
|
||||
INSERT INTO "__DevelopmentSchemaHistory" ("MigrationId", "AppliedAt")
|
||||
VALUES ({PeopleAndCoursesMigration}, {DateTime.UtcNow});
|
||||
VALUES ({migrationId}, {DateTime.UtcNow});
|
||||
""",
|
||||
cancellationToken);
|
||||
await transaction.CommitAsync(cancellationToken);
|
||||
logger.LogInformation(
|
||||
"Applied SQLite development schema migration {MigrationId}.",
|
||||
PeopleAndCoursesMigration);
|
||||
migrationId);
|
||||
}
|
||||
|
||||
private static readonly string[] PeopleAndCoursesStatements =
|
||||
@@ -166,4 +187,149 @@ public sealed class DevelopmentSqliteMigrator(
|
||||
ON "Courses" ("CollegeId", "Nature");
|
||||
"""
|
||||
];
|
||||
|
||||
private static readonly string[] CurriculumPlansStatements =
|
||||
[
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "CurriculumPlans" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_CurriculumPlans" PRIMARY KEY,
|
||||
"MajorId" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"Version" TEXT NOT NULL,
|
||||
"EffectiveGrade" INTEGER NOT NULL,
|
||||
"TotalCredits" TEXT NOT NULL,
|
||||
"Status" INTEGER NOT NULL,
|
||||
"Description" TEXT NULL,
|
||||
"PublishedAt" TEXT NULL,
|
||||
"CreatedAt" TEXT NOT NULL,
|
||||
"UpdatedAt" TEXT NOT NULL,
|
||||
CONSTRAINT "FK_CurriculumPlans_Majors_MajorId"
|
||||
FOREIGN KEY ("MajorId") REFERENCES "Majors" ("Id") ON DELETE RESTRICT
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_CurriculumPlans_MajorId_EffectiveGrade_Version"
|
||||
ON "CurriculumPlans" ("MajorId", "EffectiveGrade", "Version");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_CurriculumPlans_Status_EffectiveGrade"
|
||||
ON "CurriculumPlans" ("Status", "EffectiveGrade");
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "CurriculumModules" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_CurriculumModules" PRIMARY KEY,
|
||||
"CurriculumPlanId" TEXT NOT NULL,
|
||||
"Code" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"RequiredCredits" TEXT NOT NULL,
|
||||
"SortOrder" INTEGER NOT NULL,
|
||||
"CreatedAt" TEXT NOT NULL,
|
||||
"UpdatedAt" TEXT NOT NULL,
|
||||
CONSTRAINT "FK_CurriculumModules_CurriculumPlans_CurriculumPlanId"
|
||||
FOREIGN KEY ("CurriculumPlanId") REFERENCES "CurriculumPlans" ("Id")
|
||||
ON DELETE CASCADE
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_CurriculumModules_CurriculumPlanId_Code"
|
||||
ON "CurriculumModules" ("CurriculumPlanId", "Code");
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "CurriculumCourses" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_CurriculumCourses" PRIMARY KEY,
|
||||
"CurriculumModuleId" TEXT NOT NULL,
|
||||
"CourseId" TEXT NOT NULL,
|
||||
"RecommendedSemester" INTEGER NOT NULL,
|
||||
"Type" INTEGER NOT NULL,
|
||||
"Notes" TEXT NULL,
|
||||
"CreatedAt" TEXT NOT NULL,
|
||||
"UpdatedAt" TEXT NOT NULL,
|
||||
CONSTRAINT "FK_CurriculumCourses_CurriculumModules_CurriculumModuleId"
|
||||
FOREIGN KEY ("CurriculumModuleId") REFERENCES "CurriculumModules" ("Id")
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_CurriculumCourses_Courses_CourseId"
|
||||
FOREIGN KEY ("CourseId") REFERENCES "Courses" ("Id") ON DELETE RESTRICT
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_CurriculumCourses_CurriculumModuleId_CourseId"
|
||||
ON "CurriculumCourses" ("CurriculumModuleId", "CourseId");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_CurriculumCourses_CourseId"
|
||||
ON "CurriculumCourses" ("CourseId");
|
||||
"""
|
||||
];
|
||||
|
||||
private static readonly string[] TeachingTasksStatements =
|
||||
[
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "TeachingTasks" (
|
||||
"Id" TEXT NOT NULL CONSTRAINT "PK_TeachingTasks" PRIMARY KEY,
|
||||
"TaskNumber" TEXT NOT NULL,
|
||||
"Name" TEXT NOT NULL,
|
||||
"AcademicTermId" TEXT NOT NULL,
|
||||
"CourseId" TEXT NOT NULL,
|
||||
"Capacity" INTEGER NOT NULL,
|
||||
"StartWeek" INTEGER NOT NULL,
|
||||
"EndWeek" INTEGER NOT NULL,
|
||||
"WeeklyHours" INTEGER NOT NULL,
|
||||
"Status" INTEGER NOT NULL,
|
||||
"Notes" TEXT NULL,
|
||||
"PublishedAt" TEXT NULL,
|
||||
"CreatedAt" TEXT NOT NULL,
|
||||
"UpdatedAt" TEXT NOT NULL,
|
||||
CONSTRAINT "FK_TeachingTasks_AcademicTerms_AcademicTermId"
|
||||
FOREIGN KEY ("AcademicTermId") REFERENCES "AcademicTerms" ("Id") ON DELETE RESTRICT,
|
||||
CONSTRAINT "FK_TeachingTasks_Courses_CourseId"
|
||||
FOREIGN KEY ("CourseId") REFERENCES "Courses" ("Id") ON DELETE RESTRICT
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS "IX_TeachingTasks_TaskNumber"
|
||||
ON "TeachingTasks" ("TaskNumber");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_TeachingTasks_AcademicTermId_Status"
|
||||
ON "TeachingTasks" ("AcademicTermId", "Status");
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_TeachingTasks_CourseId"
|
||||
ON "TeachingTasks" ("CourseId");
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "TeachingTaskTeachers" (
|
||||
"TeachingTaskId" TEXT NOT NULL,
|
||||
"TeacherId" TEXT NOT NULL,
|
||||
"IsPrimary" INTEGER NOT NULL,
|
||||
CONSTRAINT "PK_TeachingTaskTeachers"
|
||||
PRIMARY KEY ("TeachingTaskId", "TeacherId"),
|
||||
CONSTRAINT "FK_TeachingTaskTeachers_TeachingTasks_TeachingTaskId"
|
||||
FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_TeachingTaskTeachers_Teachers_TeacherId"
|
||||
FOREIGN KEY ("TeacherId") REFERENCES "Teachers" ("Id") ON DELETE RESTRICT
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_TeachingTaskTeachers_TeacherId"
|
||||
ON "TeachingTaskTeachers" ("TeacherId");
|
||||
""",
|
||||
"""
|
||||
CREATE TABLE IF NOT EXISTS "TeachingTaskClasses" (
|
||||
"TeachingTaskId" TEXT NOT NULL,
|
||||
"AdministrativeClassId" TEXT NOT NULL,
|
||||
CONSTRAINT "PK_TeachingTaskClasses"
|
||||
PRIMARY KEY ("TeachingTaskId", "AdministrativeClassId"),
|
||||
CONSTRAINT "FK_TeachingTaskClasses_TeachingTasks_TeachingTaskId"
|
||||
FOREIGN KEY ("TeachingTaskId") REFERENCES "TeachingTasks" ("Id") ON DELETE CASCADE,
|
||||
CONSTRAINT "FK_TeachingTaskClasses_AdministrativeClasses_AdministrativeClassId"
|
||||
FOREIGN KEY ("AdministrativeClassId") REFERENCES "AdministrativeClasses" ("Id")
|
||||
ON DELETE RESTRICT
|
||||
);
|
||||
""",
|
||||
"""
|
||||
CREATE INDEX IF NOT EXISTS "IX_TeachingTaskClasses_AdministrativeClassId"
|
||||
ON "TeachingTaskClasses" ("AdministrativeClassId");
|
||||
"""
|
||||
];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user