重构项目结构,移除Assignment相关功能,优化Submission模块
Some checks failed
TechAct / explore-gitea-actions (push) Failing after 12s

This commit is contained in:
SpecialX
2025-10-09 18:57:28 +08:00
parent 403b34a098
commit ac900159ba
289 changed files with 11948 additions and 20150 deletions

View File

@@ -1,5 +1,4 @@
using TechHelper.Context.Configuration;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Entities.Contracts;
@@ -11,31 +10,29 @@ namespace TechHelper.Context
public ApplicationContext(DbContextOptions options)
: base(options) { }
public DbSet<AssignmentClass> AssignmentClasses { get; set; }
public DbSet<Assignment> Assignments { get; set; }
public DbSet<AssignmentQuestion> AssignmentQuestions { get; set; }
public DbSet<School> Schools { get; set; }
public DbSet<Grade> Grades { get; set; }
public DbSet<Class> Classes { get; set; }
public DbSet<ClassTeacher> ClassStudents { get; set; }
public DbSet<ClassTeacher> ClassTeachers { get; set; }
public DbSet<Exam> Exams { get; set; }
public DbSet<ExamQuestion> ExamQuestions { get; set; }
public DbSet<ExamAttachment> ExamAttachments{ get; set; }
public DbSet<ExamType> ExamTypes { get; set; }
public DbSet<Question> Questions { get; set; }
public DbSet<Submission> Submissions { get; set; }
public DbSet<SubmissionDetail> SubmissionDetails { get; set; }
public DbSet<QuestionContext> QuestionContexts { get; set; }
public DbSet<Global> Globals { get; set; }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.ApplyConfiguration(new RoleConfiguration());
builder.ApplyConfiguration(new AssignmentConfiguration());
builder.ApplyConfiguration(new AssignmentClassConfiguration());
builder.ApplyConfiguration(new AssignmentQuestionConfiguration());
builder.ApplyConfiguration(new ClassConfiguration());
builder.ApplyConfiguration(new ClassStudentConfiguration());
builder.ApplyConfiguration(new ClassTeacherConfiguration());
builder.ApplyConfiguration(new QuestionConfiguration());
builder.ApplyConfiguration(new SubmissionConfiguration());
builder.ApplyConfiguration(new SubmissionDetailConfiguration());
}
//protected override void OnModelCreating(ModelBuilder builder)
//{
// base.OnModelCreating(builder);
// builder.ApplyConfiguration(new RoleConfiguration());
// builder.ApplyConfiguration(new AssignmentConfiguration());
// builder.ApplyConfiguration(new AssignmentClassConfiguration());
// builder.ApplyConfiguration(new AssignmentQuestionConfiguration());
// builder.ApplyConfiguration(new ClassConfiguration());
// builder.ApplyConfiguration(new QuestionConfiguration());
// builder.ApplyConfiguration(new SubmissionConfiguration());
// builder.ApplyConfiguration(new SubmissionDetailConfiguration());
//}
}
}

View File

@@ -1,11 +1,7 @@
using AutoMapper;
using AutoMapper.Internal.Mappers;
using Entities.Contracts;
using Entities.DTO;
using Newtonsoft.Json;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using Entities.DTO.Class;
namespace TechHelper.Context
{
@@ -28,53 +24,91 @@ namespace TechHelper.Context
{
CreateMap<UserForRegistrationDto, User>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.Name))
.ForMember(dest => dest.UserName, opt => opt.MapFrom(src => src.DisplayName))
.ForMember(dest => dest.Email, opt => opt.MapFrom(src => src.Email))
.ForMember(dest => dest.PhoneNumber, opt => opt.MapFrom(src => src.PhoneNumber))
.ForMember(dest => dest.Address, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.HomeAddress, opt => opt.MapFrom(src => src.HomeAddress))
.ForMember(dest => dest.PasswordHash, opt => opt.Ignore())
.ForMember(dest => dest.EmailConfirmed, opt => opt.Ignore());
CreateMap<ClassDto, Class>()
.ForMember(d => d.Number, o => o.MapFrom(src => src.Class))
.ReverseMap();
// Subject
CreateMap<Subject, SubjectDto>().ReverseMap();
CreateMap<Subject, SubjectResponseDto>().ReverseMap();
CreateMap<Subject, TypeCommonDto>().ReverseMap();
// ExamType
CreateMap<ExamType, ExamTypeDto>().ReverseMap();
CreateMap<ExamType, TypeCommonDto>().ReverseMap();
// QuestionType
CreateMap<QuestionType, QuestionTypeDto >().ReverseMap();
CreateMap<QuestionType, TypeCommonDto>().ReverseMap();
// Exam
CreateMap<ExamDto, Exam>().ReverseMap();
CreateMap<Exam, ExamListDto>().ReverseMap();
// Assignment
CreateMap<AssignmentDto, Assignment>().ReverseMap();
CreateMap<AssignmentQuestionDto, AssignmentQuestion>().ReverseMap();
CreateMap<ExamQuestionDto, ExamQuestion>().ReverseMap();
CreateMap<QuestionDto, Question>().ReverseMap();
CreateMap<QuestionContext, QuestionContextDto>().ReverseMap();
// Submission
CreateMap<SubmissionDto, Submission>().ReverseMap();
CreateMap<SubmissionDetailDto, SubmissionDetail>().ReverseMap();
CreateMap<SubmissionTeacherUpdateDto, Submission>().ReverseMap();
// Student Submission Detail
CreateMap<Submission, StudentSubmissionDetailDto>()
.ForMember(dest => dest.AssignmentId, opt => opt.MapFrom(src => src.AssignmentId))
.ForMember(dest => dest.AssignmentId, opt => opt.MapFrom(src => src.ExamId))
.ForMember(dest => dest.StudentId, opt => opt.MapFrom(src => src.StudentId))
.ForMember(dest => dest.SubmissionTime, opt => opt.MapFrom(src => src.SubmissionTime))
.ForMember(dest => dest.OverallGrade, opt => opt.MapFrom(src => src.OverallGrade))
.ForMember(dest => dest.OverallFeedback, opt => opt.MapFrom(src => src.OverallFeedback))
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status));
CreateMap<Assignment, AssignmentDto>().ReverseMap();
CreateMap<Submission, SubmissionListDto>().ReverseMap();
CreateMap<SubmissionDetail, SubmissionDetailTeacherUpdateDto>().ReverseMap();
CreateMap<SubjectTypeMetadataDto, Global>()
.ForMember(dest => dest.Info, opt => opt.MapFrom(src => JsonConvert.SerializeObject(src.Data)));
CreateMap<Global, SubjectTypeMetadataDto>()
.ForMember(dest => dest.Data, opt => opt.MapFrom(src => JsonConvert.DeserializeObject<Dictionary<string, (string Color, string DisplayName)>>(src.Info)));
// School
CreateMap<SchoolDto, School>().ReverseMap();
CreateMap<SchoolResponseDto, School>().ReverseMap();
// Grade
CreateMap<GradeDto, Grade>().ReverseMap();
CreateMap<CreateGradeDto, Grade>().ReverseMap();
// Class
CreateMap<ClassDto, Class>().ReverseMap();
CreateMap<ClassCreateDto, Class>().ReverseMap();
// User
CreateMap<User, UserDto>().ReverseMap();
CreateMap<User, UserListDto>().ReverseMap();
// KeyPoint
CreateMap<KeyPoint, KeyPointDto>().ReverseMap();
CreateMap<KeyPoint, CreateKeyPointDto>().ReverseMap();
CreateMap<KeyPoint, UpdateKeyPointDto>().ReverseMap();
CreateMap<KeyPoint, KeyPointResponseDto>().ReverseMap();
// Lesson
CreateMap<Lesson, LessonDto>().ReverseMap();
CreateMap<Lesson, CreateLessonDto>().ReverseMap();
CreateMap<Lesson, UpdateLessonDto>().ReverseMap();
CreateMap<Lesson, LessonResponseDto>().ReverseMap();
// Textbook
CreateMap<Textbook, TextbookDto>().ReverseMap();
CreateMap<Textbook, CreateTextbookDto>().ReverseMap();
CreateMap<Textbook, UpdateTextbookDto>().ReverseMap();
CreateMap<Textbook, TextbookResponseDto>()
.ForMember(dest => dest.LessonCount, opt => opt.MapFrom(src => src.Lessons.Count))
.ForMember(dest => dest.LessonTitles, opt => opt.MapFrom(src => src.Lessons.Select(l => l.Title).ToList()));
}
}

View File

@@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentAttachmentConfiguration : IEntityTypeConfiguration<AssignmentAttachment>
public class AssignmentAttachmentConfiguration : IEntityTypeConfiguration<ExamAttachment>
{
public void Configure(EntityTypeBuilder<AssignmentAttachment> builder)
public void Configure(EntityTypeBuilder<ExamAttachment> builder)
{
builder.ToTable("assignment_attachments");
@@ -38,8 +38,8 @@ namespace TechHelper.Context.Configuration
.HasDefaultValue(false);
// Configure the relationship explicitly
builder.HasOne(aa => aa.Assignment) // An AssignmentAttachment has one Assignment
.WithMany(a => a.AssignmentAttachments) // An Assignment has many AssignmentAttachments (assuming 'Attachments' collection in Assignment)
builder.HasOne(aa => aa.Exam) // An AssignmentAttachment has one Assignment
.WithMany(a => a.ExamAttachments) // An Assignment has many AssignmentAttachments (assuming 'Attachments' collection in Assignment)
.HasForeignKey(aa => aa.AssignmentId) // The foreign key is AssignmentAttachment.AssignmentId
.IsRequired() // It's a required relationship based on your [Required] attribute
.OnDelete(DeleteBehavior.Cascade); // If an Assignment is deleted, its attachments should also be deleted

View File

@@ -4,18 +4,18 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentClassConfiguration : IEntityTypeConfiguration<AssignmentClass>
public class AssignmentClassConfiguration : IEntityTypeConfiguration<ExamClass>
{
public void Configure(EntityTypeBuilder<AssignmentClass> builder)
public void Configure(EntityTypeBuilder<ExamClass> builder)
{
// 设置表名为 "assignment_class"
builder.ToTable("assignment_class");
// 设置复合主键
builder.HasKey(ac => new { ac.AssignmentId, ac.ClassId });
builder.HasKey(ac => new { ac.ExamId, ac.ClassId });
// 配置 AssignmentId 列名
builder.Property(ac => ac.AssignmentId)
builder.Property(ac => ac.ExamId)
.HasColumnName("assignment_id");
// 配置 ClassId 列名
@@ -34,15 +34,15 @@ namespace TechHelper.Context.Configuration
// 配置到 Assignment 的关系 (多对一)
// 假设 Assignment 类中有一个名为 AssignmentClasses 的集合属性
builder.HasOne(ac => ac.Assignment) // AssignmentClass 有一个 Assignment
builder.HasOne(ac => ac.Exam) // AssignmentClass 有一个 Assignment
.WithMany(a => a.AssignmentClasses) // Assignment 有多个 AssignmentClass 记录
.HasForeignKey(ac => ac.AssignmentId) // 通过 AssignmentId 建立外键
.HasForeignKey(ac => ac.ExamId) // 通过 AssignmentId 建立外键
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 AssignmentClass 记录也级联删除
// 配置到 Class 的关系 (多对一)
// 假设 Class 类中有一个名为 AssignmentClasses 的集合属性
builder.HasOne(ac => ac.Class) // AssignmentClass 有一个 Class
.WithMany(c => c.AssignmentClasses) // Class 有多个 AssignmentClass 记录
.WithMany(c => c.ExamClasses) // Class 有多个 AssignmentClass 记录
.HasForeignKey(ac => ac.ClassId) // 通过 ClassId 建立外键
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 AssignmentClass 记录也级联删除
}

View File

@@ -5,9 +5,9 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace TechHelper.Context.Configuration
{
public class AssignmentConfiguration : IEntityTypeConfiguration<Assignment>
public class AssignmentConfiguration : IEntityTypeConfiguration<Exam>
{
public void Configure(EntityTypeBuilder<Assignment> builder)
public void Configure(EntityTypeBuilder<Exam> builder)
{
builder.ToTable("assignments");
@@ -61,7 +61,7 @@ namespace TechHelper.Context.Configuration
builder.HasOne(a=>a.ExamStruct)
.WithOne()
.HasForeignKey<Assignment>(a=>a.ExamStructId)
.HasForeignKey<Exam>(a=>a.ExamStructId)
.OnDelete(DeleteBehavior.Cascade);
}

View File

@@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class AssignmentQuestionConfiguration : IEntityTypeConfiguration<AssignmentQuestion>
public class AssignmentQuestionConfiguration : IEntityTypeConfiguration<ExamQuestion>
{
public void Configure(EntityTypeBuilder<AssignmentQuestion> builder)
public void Configure(EntityTypeBuilder<ExamQuestion> builder)
{
// 1. 设置表名
builder.ToTable("assignment_questions");
@@ -44,13 +44,13 @@ namespace TechHelper.Context.Configuration
builder.HasOne(aq => aq.Question)
.WithMany(q => q.AssignmentQuestions)
.WithMany(q => q.ExamQuestions)
.HasForeignKey(aq => aq.QuestionId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(aq => aq.ParentAssignmentQuestion)
builder.HasOne(aq => aq.ParentExamQuestion)
.WithMany(aq => aq.ChildrenAssignmentQuestion)
.HasForeignKey(aq => aq.ParentAssignmentQuestionId)
.HasForeignKey(aq => aq.ParentExamQuestionId)
.OnDelete(DeleteBehavior.Cascade);
builder.HasOne(aq => aq.QuestionContext)

View File

@@ -86,7 +86,7 @@ namespace TechHelper.Context.Configuration
// 11. 与 AssignmentClass 的关系 (多对多中间表或一对多)
// 一对多:一个 Class 有多个 AssignmentClass。一个 AssignmentClass 属于一个 Class。
// 假设 AssignmentClass 有 'ClassId' 外键和 'Class' 导航属性。
builder.HasMany(c => c.AssignmentClasses) // Class 中的集合导航属性
builder.HasMany(c => c.ExamClasses) // Class 中的集合导航属性
.WithOne(ac => ac.Class) // 假设 AssignmentClass 中有 'public Class Class { get; set; }'
.HasForeignKey(ac => ac.ClassId) // 假设 AssignmentClass 中有 'public Guid ClassId { get; set; }'
.OnDelete(DeleteBehavior.Cascade); // 常见:如果一个班级被删除,其作业关联也应被删除。

View File

@@ -1,64 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class ClassStudentConfiguration : IEntityTypeConfiguration<ClassStudent>
{
public void Configure(EntityTypeBuilder<ClassStudent> builder)
{
// 1. 设置表名
// 将此实体映射到数据库中名为 "class_student" 的表。
builder.ToTable("class_student");
// 2. 设置复合主键
// ClassId 和 StudentId 的组合作为主键,确保一个班级中一个学生只有一条入学记录。
builder.HasKey(cs => new { cs.ClassId, cs.StudentId });
// 3. 配置列名和属性特性
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
builder.Property(cs => cs.ClassId)
.HasColumnName("class_id");
// 配置 StudentId 属性对应的数据库列名为 "student_id"。
builder.Property(cs => cs.StudentId)
.HasColumnName("student_id");
// 配置 EnrollmentDate 属性对应的数据库列名为 "enrollment_date",并设置为必需字段。
builder.Property(cs => cs.EnrollmentDate)
.HasColumnName("enrollment_date")
.IsRequired();
// 配置 IsDeleted 属性对应的数据库列名为 "deleted",并设置默认值为 false。
builder.Property(cs => cs.IsDeleted)
.HasColumnName("deleted")
.HasDefaultValue(false); // 常用作软删除标记
// 4. 配置导航属性和外键关系
// ---
// 配置 ClassStudent 到 Class 的关系 (多对一)
// 一个 ClassStudent 联结记录属于一个 Class。
//
// 假设 `Class` 实体中有一个名为 `ClassStudents` 的 `ICollection<ClassStudent>` 集合属性。
builder.HasOne(cs => cs.Class) // 当前 ClassStudent 链接到一个 Class
.WithMany(c => c.ClassStudents) // 那个 Class 可以有多个 ClassStudent 记录
.HasForeignKey(cs => cs.ClassId) // 外键是 ClassStudent.ClassId
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassStudent 记录也级联删除。
// ---
// 配置 ClassStudent 到 User (Student) 的关系 (多对一)
// 一个 ClassStudent 联结记录属于一个 User (作为 Student)。
//
// 假设 `User` 实体中有一个名为 `EnrolledClassesLink` 的 `ICollection<ClassStudent>` 集合属性,
// 用于表示该用户所注册的班级联结记录 (与 `ClassTeacherConfiguration` 中的模式类似)。
builder.HasOne(cs => cs.Student) // 当前 ClassStudent 链接到一个 User (学生)
.WithMany(u => u.EnrolledClassesLink) // 那个 User (学生) 可以有多个 ClassStudent 记录
.HasForeignKey(cs => cs.StudentId) // 外键是 ClassStudent.StudentId
.OnDelete(DeleteBehavior.Restrict); // 当 User (学生) 被删除时,如果还有相关的 ClassStudent 记录,则会阻止删除。
// 这是更安全的做法,以避免意外数据丢失。如果你希望学生被删除时,其所有注册关系也一并删除,可改为 DeleteBehavior.Cascade。
}
}
}

View File

@@ -1,61 +0,0 @@
using Entities.Contracts;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.EntityFrameworkCore;
namespace TechHelper.Context.Configuration
{
public class ClassTeacherConfiguration : IEntityTypeConfiguration<ClassTeacher>
{
public void Configure(EntityTypeBuilder<ClassTeacher> builder)
{
// 1. 设置表名
// 将此实体映射到数据库中名为 "class_teachers" 的表。
builder.ToTable("class_teachers");
// 2. 设置复合主键
// ClassId 和 TeacherId 的组合作为主键,确保一个班级中一个老师只有一条任教记录。
// 这要求 ClassTeacher 类中的 ClassId 和 TeacherId 属性上都添加了 [Key] 特性。
builder.HasKey(ct => new { ct.ClassId, ct.TeacherId });
// 3. 配置列名和属性特性
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
builder.Property(ct => ct.ClassId)
.HasColumnName("class_id");
// 配置 TeacherId 属性对应的数据库列名为 "teacher_id"。
builder.Property(ct => ct.TeacherId)
.HasColumnName("teacher_id");
// 配置 SubjectTaught 属性对应的数据库列名为 "subject_taught"。
// 假设 SubjectTaught 可以为空,所以没有 .IsRequired()
builder.Property(ct => ct.SubjectTaught)
.HasColumnName("subject_taught");
// 4. 配置导航属性和外键关系
// ---
// 配置 ClassTeacher 到 Class 的关系 (多对一)
// 一个 ClassTeacher 联结记录属于一个 Class。
//
// 假设 `Class` 实体中有一个名为 `ClassTeachers` 的 `ICollection<ClassTeacher>` 集合属性。
builder.HasOne(ct => ct.Class) // 当前 ClassTeacher 链接到一个 Class
.WithMany(c => c.ClassTeachers) // 那个 Class 可以有多个 ClassTeacher 记录
.HasForeignKey(ct => ct.ClassId) // 外键是 ClassTeacher.ClassId
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassTeacher 记录也级联删除。
// ---
// 配置 ClassTeacher 到 User (Teacher) 的关系 (多对一)
// 一个 ClassTeacher 联结记录属于一个 User (作为 Teacher)。
//
// 假设 `User` 实体中有一个名为 `TaughtClassesLink` 的 `ICollection<ClassTeacher>` 集合属性,
// 用于表示该用户所教授的班级联结记录。
builder.HasOne(ct => ct.Teacher) // 当前 ClassTeacher 链接到一个 User (老师)
.WithMany(u => u.TaughtClassesLink) // 那个 User (老师) 可以有多个 ClassTeacher 记录 (为所教授的班级)
.HasForeignKey(ct => ct.TeacherId) // 外键是 ClassTeacher.TeacherId
.OnDelete(DeleteBehavior.Cascade); // 当 User (老师) 被删除时,如果还有相关的 ClassTeacher 记录,则会阻止删除。
// 这通常是防止数据丢失的更安全选择。如果你希望老师被删除时,其所有任教关系也一并删除,可改为 DeleteBehavior.Cascade。
}
}
}

View File

@@ -95,7 +95,7 @@ namespace TechHelper.Context.Configuration
//
// 这个关系的外键配置通常在 "多" 的一方(`AssignmentQuestion` 实体)进行。
// 假设 `AssignmentQuestion` 实体有一个 `QuestionId` 外键和 `Question` 导航属性。
builder.HasMany(q => q.AssignmentQuestions) // 当前 Question 有多个 AssignmentQuestion
builder.HasMany(q => q.ExamQuestions) // 当前 Question 有多个 AssignmentQuestion
.WithOne(aq => aq.Question); // 每一个 AssignmentQuestion 都有一个 Question
// .HasForeignKey(aq => aq.QuestionId); // 外键的配置应在 `AssignmentQuestionConfiguration` 中进行

View File

@@ -21,7 +21,7 @@ namespace TechHelper.Context.Configuration
.HasColumnName("id");
// AssignmentId
builder.Property(s => s.AssignmentId)
builder.Property(s => s.ExamId)
.HasColumnName("assignment_id")
.IsRequired();
@@ -67,9 +67,9 @@ namespace TechHelper.Context.Configuration
builder.HasOne(s => s.Assignment) // 当前 Submission 有一个 Assignment
builder.HasOne(s => s.Exam) // 当前 Submission 有一个 Assignment
.WithMany(a => a.Submissions) // 那个 Assignment 可以有多个 Submission
.HasForeignKey(s => s.AssignmentId) // 外键是 Submission.AssignmentId
.HasForeignKey(s => s.ExamId) // 外键是 Submission.AssignmentId
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 Submission 也级联删除。

View File

@@ -23,7 +23,7 @@ namespace TechHelper.Context.Configuration
.HasColumnName("student_id")
.IsRequired();
builder.Property(sd => sd.AssignmentQuestionId)
builder.Property(sd => sd.ExamQuestionId)
.HasColumnName("assignment_question_id")
.IsRequired();
@@ -67,9 +67,9 @@ namespace TechHelper.Context.Configuration
.OnDelete(DeleteBehavior.Cascade); // 当 User (学生) 被删除时,如果他/她还有提交详情,则会阻止删除。
// 这是一个更安全的选择,以防止意外数据丢失。
builder.HasOne(sd => sd.AssignmentQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
builder.HasOne(sd => sd.ExamQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
.WithMany(aq => aq.SubmissionDetails) // 那个 AssignmentQuestion 可以有多个 SubmissionDetail 记录
.HasForeignKey(sd => sd.AssignmentQuestionId) // 外键是 SubmissionDetail.AssignmentQuestionId
.HasForeignKey(sd => sd.ExamQuestionId) // 外键是 SubmissionDetail.AssignmentQuestionId
.OnDelete(DeleteBehavior.Cascade); // 当 AssignmentQuestion 被删除时,相关的 SubmissionDetail 记录也级联删除。
}
}

View File

@@ -38,7 +38,7 @@ namespace TechHelper.Context.Configuration
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有题目,则不允许删除
// User 作为创建者,与 Assignment 的关系 (一对多)
builder.HasMany(u => u.CreatedAssignments) // 一个 User 可以创建多个作业
builder.HasMany(u => u.CreatedExams) // 一个 User 可以创建多个作业
.WithOne(a => a.Creator) // 一个 Assignment 对应一个 Creator
.HasForeignKey(a => a.CreatorId) // 外键在 Assignment.CreatedBy
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有作业,则不允许删除

View File

@@ -0,0 +1,22 @@
using Entities.Contracts;
using Microsoft.AspNetCore.Identity;
namespace TechHelper.Server.Context
{
public class DbInitializer
{
public static async Task SeedRoles(RoleManager<IdentityRole<Guid>> roleManager)
{
string[] defaultRoleName = { "Admin", "Teacher", "Student" };
foreach (var roleName in defaultRoleName)
{
if (!await roleManager.RoleExistsAsync(roleName))
{
await roleManager.CreateAsync(new IdentityRole<Guid>(roleName));
Console.WriteLine($"Default role '{roleName}' created successfully.");
}
}
}
}
}