发布课表投影改为数据库端删除旧数据、每 2,000 条分批写入并及时释放 EF 跟踪对象,避免大规模发布时内存持续增长。
为“空闲教室/预约占用”新增 学期 + 周次 + 星期 + 节次 + 场地 查询索引;新发布课表的该查询已优先走课次明细投影。
This commit is contained in:
@@ -543,6 +543,14 @@ public sealed class AppDbContext(DbContextOptions<AppDbContext> options)
|
||||
builder.Entity<PublishedScheduleOccurrence>(entity =>
|
||||
{
|
||||
entity.HasIndex(x => new { x.AcademicTermId, x.TeachingTaskId, x.Week });
|
||||
entity.HasIndex(x => new
|
||||
{
|
||||
x.AcademicTermId,
|
||||
x.Week,
|
||||
x.DayOfWeek,
|
||||
x.StartPeriod,
|
||||
x.ClassroomId
|
||||
});
|
||||
entity.HasIndex(x => new { x.SchedulePlanId, x.ClassroomId, x.Week, x.DayOfWeek, x.StartPeriod });
|
||||
entity.HasIndex(x => new { x.ScheduleEntryId, x.Week }).IsUnique();
|
||||
entity.HasOne(x => x.ScheduleEntry).WithMany().HasForeignKey(x => x.ScheduleEntryId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
+6741
File diff suppressed because it is too large
Load Diff
+27
@@ -0,0 +1,27 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class OptimizePublishedTimetableOccurrenceLookup : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_PublishedScheduleOccurrences_AcademicTermId_Week_DayOfWeek_S~",
|
||||
table: "PublishedScheduleOccurrences",
|
||||
columns: new[] { "AcademicTermId", "Week", "DayOfWeek", "StartPeriod", "ClassroomId" });
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_PublishedScheduleOccurrences_AcademicTermId_Week_DayOfWeek_S~",
|
||||
table: "PublishedScheduleOccurrences");
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
@@ -3552,6 +3552,8 @@ namespace Jiaowu.Api.Infrastructure.Persistence.Migrations.MySql
|
||||
|
||||
b.HasIndex("AcademicTermId", "TeachingTaskId", "Week");
|
||||
|
||||
b.HasIndex("AcademicTermId", "Week", "DayOfWeek", "StartPeriod", "ClassroomId");
|
||||
|
||||
b.HasIndex("SchedulePlanId", "ClassroomId", "Week", "DayOfWeek", "StartPeriod");
|
||||
|
||||
b.ToTable("PublishedScheduleOccurrences");
|
||||
|
||||
@@ -6,6 +6,7 @@ namespace Jiaowu.Api.Infrastructure.Timetables;
|
||||
|
||||
public sealed class PublishedTimetableProjectionService(AppDbContext db)
|
||||
{
|
||||
private const int WriteBatchSize = 2_000;
|
||||
public async Task RebuildPublishedPlansForTaskAsync(Guid teachingTaskId, CancellationToken cancellationToken)
|
||||
{
|
||||
var plans = await db.SchedulePlans
|
||||
@@ -19,10 +20,11 @@ public sealed class PublishedTimetableProjectionService(AppDbContext db)
|
||||
|
||||
public async Task RebuildAsync(SchedulePlan plan, CancellationToken cancellationToken)
|
||||
{
|
||||
var previous = db.PublishedScheduleOccurrences.Where(x => x.SchedulePlanId == plan.Id);
|
||||
db.PublishedScheduleOccurrences.RemoveRange(previous);
|
||||
await db.PublishedScheduleOccurrences
|
||||
.Where(x => x.SchedulePlanId == plan.Id)
|
||||
.ExecuteDeleteAsync(cancellationToken);
|
||||
|
||||
var rows = new List<PublishedScheduleOccurrence>();
|
||||
var rows = new List<PublishedScheduleOccurrence>(WriteBatchSize);
|
||||
foreach (var entry in plan.Entries)
|
||||
for (var week = entry.StartWeek; week <= entry.EndWeek; week++)
|
||||
{
|
||||
@@ -41,8 +43,21 @@ public sealed class PublishedTimetableProjectionService(AppDbContext db)
|
||||
PeriodCount = entry.PeriodCount,
|
||||
Kind = entry.Kind
|
||||
});
|
||||
if (rows.Count == WriteBatchSize)
|
||||
await WriteBatchAsync(rows, cancellationToken);
|
||||
}
|
||||
if (rows.Count > 0)
|
||||
await WriteBatchAsync(rows, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task WriteBatchAsync(
|
||||
List<PublishedScheduleOccurrence> rows,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
db.PublishedScheduleOccurrences.AddRange(rows);
|
||||
await db.SaveChangesAsync(cancellationToken);
|
||||
foreach (var row in rows)
|
||||
db.Entry(row).State = EntityState.Detached;
|
||||
rows.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user