struct&&assiQues
This commit is contained in:
@@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Entities.Contracts;
|
||||
using TechHelper.Server.Context.Configuration;
|
||||
|
||||
namespace TechHelper.Context
|
||||
{
|
||||
@@ -36,7 +35,6 @@ namespace TechHelper.Context
|
||||
builder.ApplyConfiguration(new ClassTeacherConfiguration());
|
||||
builder.ApplyConfiguration(new QuestionConfiguration());
|
||||
builder.ApplyConfiguration(new SubmissionConfiguration());
|
||||
builder.ApplyConfiguration(new QuestionGroupConfiguration());
|
||||
builder.ApplyConfiguration(new SubmissionDetailConfiguration());
|
||||
}
|
||||
}
|
||||
|
@@ -36,60 +36,41 @@ namespace TechHelper.Context
|
||||
|
||||
CreateMap<SubQuestionDto, Question>()
|
||||
.ForMember(dest => dest.Id, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.QuestionText, opt => opt.MapFrom(src => src.Stem))
|
||||
.ForMember(dest => dest.CorrectAnswer, opt => opt.MapFrom(src => src.SampleAnswer))
|
||||
.ForMember(dest => dest.QuestionType, opt => opt.MapFrom(src => EnumMappingHelpers.ParseEnumSafe(src.QuestionType, QuestionType.Unknown)))
|
||||
.ForMember(dest => dest.Title, opt => opt.MapFrom(src => src.Stem))
|
||||
.ForMember(dest => dest.Answer, opt => opt.MapFrom(src => src.SampleAnswer))
|
||||
.ForMember(dest => dest.Type, opt => opt.MapFrom(src => EnumMappingHelpers.ParseEnumSafe(src.QuestionType, QuestionType.Unknown)))
|
||||
.ForMember(dest => dest.DifficultyLevel, opt => opt.MapFrom(src => EnumMappingHelpers.ParseEnumSafe(src.DifficultyLevel, DifficultyLevel.easy)))
|
||||
.ForMember(dest => dest.SubjectArea, opt => opt.MapFrom(src => EnumMappingHelpers.ParseEnumSafe(src.DifficultyLevel, SubjectAreaEnum.Unknown)))
|
||||
.ForMember(dest => dest.CreatedBy, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.CreatorId, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.CreatedAt, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.UpdatedAt, opt => opt.Ignore())
|
||||
.ForMember(dest => dest.IsDeleted, opt => opt.Ignore());
|
||||
|
||||
// 2. Question -> SubQuestionDto (查看时)
|
||||
CreateMap<Question, SubQuestionDto>()
|
||||
.ForMember(dest => dest.Stem, opt => opt.MapFrom(src => src.QuestionText))
|
||||
.ForMember(dest => dest.Score, opt => opt.Ignore()) // Question 实体没有 Score 字段,需要从 AssignmentQuestion 获取
|
||||
.ForMember(dest => dest.SampleAnswer, opt => opt.MapFrom(src => src.CorrectAnswer))
|
||||
.ForMember(dest => dest.QuestionType, opt => opt.MapFrom(src => src.QuestionType.ToString()))
|
||||
.ForMember(dest => dest.DifficultyLevel, opt => opt.MapFrom(src => src.DifficultyLevel.ToString()))
|
||||
.ForMember(dest => dest.Options, opt => opt.Ignore()); // Options 需要单独处理
|
||||
|
||||
CreateMap<Assignment, ExamDto>()
|
||||
.ForMember(dest => dest.AssignmentTitle, opt => opt.MapFrom(src => src.Title))
|
||||
.ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description))
|
||||
.ForMember(dest => dest.AssignmentId, opt => opt.MapFrom(src => src.Id))
|
||||
.ForMember(dest => dest.QuestionGroups, opt => opt.MapFrom(src =>
|
||||
src.AssignmentGroups.FirstOrDefault(ag => ag.ParentGroup == null)))
|
||||
.ForMember(dest => dest.SubjectArea, opt => opt.MapFrom(src => src.SubjectArea.ToString()));
|
||||
// =============================================================
|
||||
// ENTITY -> DTO Mappings (用于读取/查询)
|
||||
// =============================================================
|
||||
CreateMap<Assignment, AssignmentDto>()
|
||||
.ForMember(dest => dest.ExamStruct, opt => opt.MapFrom(src => src.ExamStruct));
|
||||
|
||||
CreateMap<AssignmentGroup, QuestionGroupDto>()
|
||||
.ForMember(dest => dest.SubQuestionGroups, opt => opt.MapFrom(src => src.ChildAssignmentGroups))
|
||||
.ForMember(dest => dest.SubQuestions, opt => opt.MapFrom(src => src.AssignmentQuestions));
|
||||
CreateMap<AssignmentStruct, AssignmentStructDto>(); // 直接映射,因为成员现在对等了
|
||||
|
||||
CreateMap<AssignmentQuestion, SubQuestionDto>()
|
||||
.ForMember(dest => dest.Stem, opt => opt.MapFrom(src => src.Question.QuestionText))
|
||||
.ForMember(dest => dest.SampleAnswer, opt => opt.MapFrom(src => src.Question.CorrectAnswer))
|
||||
.ForMember(dest => dest.QuestionType, opt => opt.MapFrom(src => src.Question.QuestionType.ToString()))
|
||||
.ForMember(dest => dest.DifficultyLevel, opt => opt.MapFrom(src => src.Question.DifficultyLevel.ToString()));
|
||||
// 新增!从实体到新的 DTO 的映射
|
||||
CreateMap<AssignmentQuestion, AssignmentQuestionDto>();
|
||||
|
||||
CreateMap<Question, QuestionDto>();
|
||||
|
||||
// =================================================================
|
||||
// DTO -> ENTITY Mappings (用于创建/更新) - 现在变得极其简单!
|
||||
// =================================================================
|
||||
CreateMap<AssignmentDto, Assignment>();
|
||||
CreateMap<AssignmentStructDto, AssignmentStruct>();
|
||||
|
||||
CreateMap<QuestionGroupDto, AssignmentGroup>()
|
||||
.ForMember(dest => dest.ChildAssignmentGroups, opt => opt.MapFrom(src => src.SubQuestionGroups))
|
||||
.ForMember(dest => dest.AssignmentQuestions, opt => opt.MapFrom(src => src.SubQuestions));
|
||||
// 新增!从新的 DTO 到实体的映射
|
||||
CreateMap<AssignmentQuestionDto, AssignmentQuestion>();
|
||||
|
||||
CreateMap<SubQuestionDto, AssignmentQuestion>()
|
||||
.ForMember(dest => dest.Question, opt => opt.MapFrom(src => src)); // 映射到嵌套的 Question 对象
|
||||
CreateMap<QuestionDto, Question>();
|
||||
|
||||
CreateMap<QuestionGroupDto, QuestionGroup>()
|
||||
.ForMember(dest => dest.ChildQuestionGroups, opt => opt.MapFrom(src => src.SubQuestionGroups))
|
||||
.ForMember(dest => dest.Title, opt => opt.MapFrom(src => src.Title))
|
||||
.ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Descript));
|
||||
|
||||
|
||||
|
||||
CreateMap<Assignment, ExamDto>();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -29,10 +29,10 @@ namespace TechHelper.Context.Configuration
|
||||
.IsRequired()
|
||||
.HasColumnName("due_date");
|
||||
|
||||
builder.Property(a => a.TotalPoints)
|
||||
builder.Property(a => a.TotalQuestions)
|
||||
.HasColumnName("total_points");
|
||||
|
||||
builder.Property(a => a.CreatedBy)
|
||||
builder.Property(a => a.CreatorId)
|
||||
.HasColumnName("created_by");
|
||||
|
||||
builder.Property(a => a.CreatedAt)
|
||||
@@ -54,7 +54,7 @@ namespace TechHelper.Context.Configuration
|
||||
// 如果 User 有一个名为 AssignmentsCreated 的导航属性,应写为 .WithMany(u => u.AssignmentsCreated)
|
||||
builder.HasOne(a => a.Creator)
|
||||
.WithMany() // User 实体没有指向 Assignment 的导航属性 (或我们不知道)
|
||||
.HasForeignKey(a => a.CreatedBy)
|
||||
.HasForeignKey(a => a.CreatorId)
|
||||
.IsRequired(); // CreatedBy 是必填的,对应 [Required] 在外键属性上
|
||||
|
||||
// 关系: Assignment (一) 到 AssignmentClass (多)
|
||||
|
@@ -4,9 +4,9 @@ using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentGroupConfiguration : IEntityTypeConfiguration<AssignmentGroup>
|
||||
public class AssignmentGroupConfiguration : IEntityTypeConfiguration<AssignmentStruct>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<AssignmentGroup> builder)
|
||||
public void Configure(EntityTypeBuilder<AssignmentStruct> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
// 将此实体映射到数据库中名为 "assignment_detail" 的表。
|
||||
@@ -34,23 +34,23 @@ namespace TechHelper.Context.Configuration
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// 配置 Descript 属性对应的数据库列名为 "descript",并设置最大长度。
|
||||
builder.Property(ag => ag.Descript)
|
||||
builder.Property(ag => ag.Description)
|
||||
.HasColumnName("descript")
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// 配置 TotalPoints 属性对应的数据库列名为 "total_points"。
|
||||
// TotalPoints 是 decimal? 类型,默认就是可选的,无需 IsRequired(false)。
|
||||
builder.Property(ag => ag.TotalPoints)
|
||||
builder.Property(ag => ag.Score)
|
||||
.HasColumnName("total_points");
|
||||
|
||||
// 配置 Number 属性对应的数据库列名为 "number"。
|
||||
builder.Property(ag => ag.Number)
|
||||
builder.Property(ag => ag.Index)
|
||||
.HasColumnName("number")
|
||||
.IsRequired(); // byte 默认非空,显式 IsRequired 增加可读性。
|
||||
|
||||
// 配置 ParentGroup 属性对应的数据库列名为 "sub_group"。
|
||||
// ParentGroup 是 Guid? 类型,默认就是可选的,无需 IsRequired(false)。
|
||||
builder.Property(ag => ag.ParentGroup)
|
||||
builder.Property(ag => ag.ParentStructId)
|
||||
.HasColumnName("parent_group")
|
||||
.IsRequired(false);
|
||||
|
||||
@@ -64,16 +64,16 @@ namespace TechHelper.Context.Configuration
|
||||
// 配置 AssignmentGroup 到 Assignment 的多对一关系。
|
||||
// 一个 AssignmentGroup 记录属于一个 Assignment。
|
||||
builder.HasOne(ag => ag.Assignment) // 当前 AssignmentGroup 有一个 Assignment
|
||||
.WithMany(a => a.AssignmentGroups) // 该 Assignment 可以有多个 AssignmentGroup 记录
|
||||
.HasForeignKey(ag => ag.AssignmentId) // 通过 AssignmentId 建立外键
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当关联的 Assignment 被删除时,其所有相关的 AssignmentGroup 记录也级联删除。
|
||||
.WithOne(a => a.ExamStruct) // 该 Assignment 可以有多个 AssignmentGroup 记录
|
||||
.HasForeignKey<AssignmentStruct>(ag => ag.AssignmentId); // 通过 AssignmentId 建立外键
|
||||
|
||||
|
||||
// 配置 AssignmentGroup 到 AssignmentGroup 的自引用关系(父子关系)。
|
||||
// 一个 AssignmentGroup 可以有一个父 AssignmentGroup (SubAssignmentGroup)。
|
||||
// 假设父 AssignmentGroup 实体中有一个名为 ChildAssignmentGroups 的集合属性来表示它所包含的所有子组。
|
||||
builder.HasOne(ag => ag.ParentAssignmentGroup) // 当前 AssignmentGroup 有一个父 AssignmentGroup
|
||||
.WithMany(parentAg => parentAg.ChildAssignmentGroups) // 该父 AssignmentGroup 可以有多个子 AssignmentGroup
|
||||
.HasForeignKey(ag => ag.ParentGroup) // 通过 SubGroup 建立外键
|
||||
builder.HasOne(ag => ag.ParentStruct) // 当前 AssignmentGroup 有一个父 AssignmentGroup
|
||||
.WithMany(parentAg => parentAg.ChildrenGroups) // 该父 AssignmentGroup 可以有多个子 AssignmentGroup
|
||||
.HasForeignKey(ag => ag.ParentStructId) // 通过 SubGroup 建立外键
|
||||
.IsRequired(false) // SubGroup 是可空的 (Guid?),所以这个关系是可选的。
|
||||
.OnDelete(DeleteBehavior.SetNull); // 当父 AssignmentGroup 被删除时,其子 AssignmentGroup 的 SubGroup 外键将被设置为 NULL。
|
||||
// 如果你希望父组被删除时子组不能脱离父组(即不允许父组被删除),
|
||||
|
@@ -25,12 +25,8 @@ namespace TechHelper.Context.Configuration
|
||||
.HasColumnName("question_id");
|
||||
|
||||
|
||||
builder.Property(aq => aq.QuestionGroupId)
|
||||
.HasColumnName("question_group_id");
|
||||
|
||||
|
||||
// 配置 QuestionNumber 列
|
||||
builder.Property(aq => aq.QuestionNumber)
|
||||
builder.Property(aq => aq.Index)
|
||||
.HasColumnName("question_number")
|
||||
.IsRequired(); // uint 类型默认非空
|
||||
|
||||
@@ -44,15 +40,10 @@ namespace TechHelper.Context.Configuration
|
||||
|
||||
// 配置 AssignmentGroupId 列
|
||||
// 该列在数据库中名为 "detail_id"
|
||||
builder.Property(aq => aq.AssignmentGroupId)
|
||||
builder.Property(aq => aq.AssignmentStructId)
|
||||
.HasColumnName("group_id")
|
||||
.IsRequired();
|
||||
|
||||
|
||||
builder.Property(aq => aq.IsGroup)
|
||||
.HasColumnName("is_group") // 修正为一致的列名
|
||||
.IsRequired(); // IsGroup 应该是必需的
|
||||
// 配置 IsDeleted 列
|
||||
builder.Property(aq => aq.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 适用于软删除策略
|
||||
@@ -69,12 +60,6 @@ namespace TechHelper.Context.Configuration
|
||||
.HasForeignKey(aq => aq.QuestionId) // 外键是 AssignmentQuestion.QuestionId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Question 被删除时,相关的 AssignmentQuestion 也级联删除。
|
||||
|
||||
builder.HasOne(aq => aq.QuestionGroup)
|
||||
.WithMany(qg => qg.AssignmentQuestions)
|
||||
.HasForeignKey(aq => aq.QuestionGroupId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
|
||||
// ---
|
||||
// 配置 AssignmentQuestion 到 AssignmentGroup 的关系 (多对一)
|
||||
// 一个 AssignmentQuestion 属于一个 AssignmentGroup。
|
||||
@@ -82,9 +67,9 @@ namespace TechHelper.Context.Configuration
|
||||
// 你的 `AssignmentQuestion` 类现在有了 `public AssignmentGroup AssignmentGroup { get; set; }`
|
||||
// 这是一个非常好的改进,它与 `AssignmentGroupId` 外键完美匹配。
|
||||
// 假设 `AssignmentGroup` 实体中有一个名为 `AssignmentQuestions` 的 `ICollection<AssignmentQuestion>` 集合属性。
|
||||
builder.HasOne(aq => aq.AssignmentGroup) // 当前 AssignmentQuestion 有一个 AssignmentGroup
|
||||
builder.HasOne(aq => aq.AssignmentStruct) // 当前 AssignmentQuestion 有一个 AssignmentGroup
|
||||
.WithMany(ag => ag.AssignmentQuestions) // 那个 AssignmentGroup 可以有多个 AssignmentQuestion
|
||||
.HasForeignKey(aq => aq.AssignmentGroupId) // 外键是 AssignmentQuestion.AssignmentGroupId (列名 detail_id)
|
||||
.HasForeignKey(aq => aq.AssignmentStructId) // 外键是 AssignmentQuestion.AssignmentGroupId (列名 detail_id)
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 AssignmentGroup 被删除时,相关的 AssignmentQuestion 也级联删除。
|
||||
|
||||
// ---
|
||||
|
@@ -0,0 +1,17 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class KeyPointConfiguration : IEntityTypeConfiguration<KeyPoint>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<KeyPoint> builder)
|
||||
{
|
||||
builder.HasOne(kp=>kp.Lesson)
|
||||
.WithMany(l => l.KeyPoints)
|
||||
.HasForeignKey(kp => kp.LessonID)
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
@@ -14,7 +14,8 @@ namespace TechHelper.Context.Configuration
|
||||
// 2. 设置主键
|
||||
builder.HasKey(q => q.Id);
|
||||
|
||||
builder.HasIndex(q => q.QuestionText);
|
||||
builder.HasIndex(q => q.Title)
|
||||
.HasPrefixLength(20);
|
||||
|
||||
// 3. 配置列名、必需性、长度及其他属性
|
||||
|
||||
@@ -23,44 +24,37 @@ namespace TechHelper.Context.Configuration
|
||||
.HasColumnName("id");
|
||||
// 对于 Guid 类型的主键,EF Core 默认由应用程序生成值,无需 ValueGeneratedOnAdd()
|
||||
|
||||
builder.Property(q => q.QuestionGroupId)
|
||||
.HasColumnName("question_group_id")
|
||||
.IsRequired(false); // 可为空,因为题目不一定属于某个题组
|
||||
|
||||
|
||||
// QuestionText
|
||||
builder.Property(q => q.QuestionText)
|
||||
builder.Property(q => q.Title)
|
||||
.HasColumnName("question_text")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// QuestionType (枚举作为字符串存储)
|
||||
builder.Property(q => q.QuestionType)
|
||||
builder.Property(q => q.Type)
|
||||
.HasColumnName("question_type")
|
||||
.IsRequired()
|
||||
.HasConversion<string>() // <-- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(20); // <-- 应用最大长度
|
||||
.HasMaxLength(20);
|
||||
|
||||
// CorrectAnswer
|
||||
builder.Property(q => q.CorrectAnswer)
|
||||
builder.Property(q => q.Answer)
|
||||
.HasColumnName("correct_answer")
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
.HasMaxLength(65535);
|
||||
|
||||
// DifficultyLevel (枚举作为字符串存储)
|
||||
builder.Property(q => q.DifficultyLevel)
|
||||
.HasColumnName("difficulty_level")
|
||||
.HasConversion<string>() // <-- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(10); // <-- 应用最大长度
|
||||
// DifficultyLevel 属性没有 [Required],所以默认是可选的
|
||||
.HasMaxLength(10);
|
||||
|
||||
|
||||
// SubjectArea
|
||||
builder.Property(q => q.SubjectArea)
|
||||
.HasColumnName("subject_area")
|
||||
.HasConversion<string>() // <--- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(100); // <--- 应用最大长度 (从原 StringLength 继承)
|
||||
.HasMaxLength(100);
|
||||
|
||||
// CreatedBy
|
||||
builder.Property(q => q.CreatedBy)
|
||||
builder.Property(q => q.CreatorId)
|
||||
.HasColumnName("created_by")
|
||||
.IsRequired();
|
||||
|
||||
@@ -91,7 +85,7 @@ namespace TechHelper.Context.Configuration
|
||||
// 假设 `User` 实体中有一个名为 `CreatedQuestions` 的 `ICollection<Question>` 集合属性。
|
||||
builder.HasOne(q => q.Creator) // 当前 Question 有一个 Creator
|
||||
.WithMany(u => u.CreatedQuestions) // 那个 Creator 可以创建多个 Question
|
||||
.HasForeignKey(q => q.CreatedBy) // 外键是 Question.CreatedBy
|
||||
.HasForeignKey(q => q.CreatorId) // 外键是 Question.CreatedBy
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (Creator) 被删除时,如果还有他/她创建的 Question,则会阻止删除。
|
||||
// 由于 CreatedBy 是 [Required],Prevent/Restrict 是一个安全的选择。
|
||||
|
||||
@@ -105,11 +99,24 @@ namespace TechHelper.Context.Configuration
|
||||
.WithOne(aq => aq.Question); // 每一个 AssignmentQuestion 都有一个 Question
|
||||
// .HasForeignKey(aq => aq.QuestionId); // 外键的配置应在 `AssignmentQuestionConfiguration` 中进行
|
||||
|
||||
builder.HasOne(q => q.QuestionGroup) // Question 实体中的 QuestionGroup 导航属性
|
||||
.WithMany(qg => qg.Questions) // QuestionGroup 实体中的 Questions 集合
|
||||
.HasForeignKey(q => q.QuestionGroupId) // Question 实体中的 QuestionGroupId 外键
|
||||
.IsRequired(false) // QuestionGroupId 在 Question 实体中是可空的
|
||||
.OnDelete(DeleteBehavior.SetNull); // 如果 QuestionGroup 被删除,关联的 Question 的外键设置为 NULL
|
||||
|
||||
builder.HasOne(q => q.KeyPoint)
|
||||
.WithMany(kp => kp.Questions)
|
||||
.HasForeignKey(q => q.KeyPointId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
builder.HasOne(q => q.Lesson)
|
||||
.WithMany(kp => kp.Questions)
|
||||
.IsRequired(false)
|
||||
.HasForeignKey(q => q.LessonId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
builder.HasOne(q => q.ParentQuestion)
|
||||
.WithMany(pq => pq.ChildrenQuestion)
|
||||
.IsRequired(false)
|
||||
.HasForeignKey(q => q.ParentQuestionId)
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,111 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Entities.Contracts;
|
||||
|
||||
namespace TechHelper.Server.Context.Configuration
|
||||
{
|
||||
public class QuestionGroupConfiguration : IEntityTypeConfiguration<QuestionGroup>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<QuestionGroup> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
builder.ToTable("question_groups");
|
||||
|
||||
// 2. 设置主键
|
||||
builder.HasKey(qg => qg.Id);
|
||||
|
||||
// 3. 配置列属性
|
||||
|
||||
// Title 标题
|
||||
builder.Property(qg => qg.Title)
|
||||
.HasColumnName("title")
|
||||
.HasMaxLength(255)
|
||||
.IsRequired(false); // 允许为空
|
||||
|
||||
// Description 描述内容 (Required)
|
||||
builder.Property(qg => qg.Description)
|
||||
.HasColumnName("description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext"); // 对应 MySQL 的 TEXT 或 LONGTEXT
|
||||
|
||||
// Type 类型 (例如: "ReadingComprehension", "DiagramAnalysis")
|
||||
builder.Property(qg => qg.Type)
|
||||
.HasColumnName("type")
|
||||
.HasMaxLength(50)
|
||||
.IsRequired(false); // 允许为空
|
||||
|
||||
// DifficultyLevel 难度级别 (枚举映射为字符串)
|
||||
builder.Property(qg => qg.DifficultyLevel)
|
||||
.HasColumnName("difficulty_level")
|
||||
.HasConversion<string>() // 将枚举转换为字符串存储
|
||||
.HasMaxLength(10);
|
||||
|
||||
// SubjectArea 科目领域 (枚举映射为字符串)
|
||||
builder.Property(qg => qg.SubjectArea)
|
||||
.HasColumnName("subject_area")
|
||||
.HasConversion<string>(); // 将枚举转换为字符串存储
|
||||
|
||||
// TotalQuestions 包含题目总数
|
||||
builder.Property(qg => qg.TotalQuestions)
|
||||
.HasColumnName("total_questions")
|
||||
.IsRequired();
|
||||
|
||||
// ParentQG 父题组 ID (外键,自引用关系)
|
||||
builder.Property(qg => qg.ParentQG)
|
||||
.HasColumnName("parent_question_group") // 使用你定义的列名
|
||||
.IsRequired(false); // 可为空,因为根题组没有父级
|
||||
|
||||
// CreatedBy 创建者 ID (外键)
|
||||
builder.Property(qg => qg.CreatedBy)
|
||||
.HasColumnName("created_by")
|
||||
.IsRequired();
|
||||
|
||||
// CreatedAt 创建时间
|
||||
builder.Property(qg => qg.CreatedAt)
|
||||
.HasColumnName("created_at")
|
||||
.IsRequired();
|
||||
|
||||
// UpdatedAt 更新时间
|
||||
builder.Property(qg => qg.UpdatedAt)
|
||||
.HasColumnName("updated_at")
|
||||
.IsRequired();
|
||||
|
||||
// IsDeleted 是否删除 (软删除)
|
||||
builder.Property(qg => qg.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.IsRequired();
|
||||
|
||||
// ValidGroup 是否有效
|
||||
builder.Property(qg => qg.ValidGroup)
|
||||
.HasColumnName("valid_group")
|
||||
.IsRequired();
|
||||
|
||||
// 4. 配置关系
|
||||
|
||||
// 与 User 的关系 (创建者)
|
||||
builder.HasOne(qg => qg.Creator)
|
||||
.WithMany()
|
||||
.HasForeignKey(qg => qg.CreatedBy)
|
||||
.OnDelete(DeleteBehavior.Restrict); // 阻止删除关联的 User
|
||||
|
||||
// 与 Question 的关系 (一对多)
|
||||
// 一个 QuestionGroup 可以包含多个 Question
|
||||
builder.HasMany(qg => qg.Questions)
|
||||
.WithOne(q => q.QuestionGroup) // Question 实体中的 QuestionGroup 导航属性
|
||||
.HasForeignKey(q => q.QuestionGroupId) // Question 实体中的 QuestionGroupId 外键
|
||||
.IsRequired(false) // QuestionGroupId 在 Question 实体中是可空的
|
||||
.OnDelete(DeleteBehavior.SetNull); // 如果 QuestionGroup 被删除,关联的 Question 的外键设置为 NULL
|
||||
|
||||
// 与自身的自引用关系 (父子题组)
|
||||
// 一个 QuestionGroup 可以有多个 ChildQuestionGroups
|
||||
builder.HasMany(qg => qg.ChildQuestionGroups)
|
||||
.WithOne(childQG => childQG.ParentQuestionGroup) // 子 QuestionGroup 实体中的 ParentQuestionGroup 导航属性
|
||||
.HasForeignKey(childQG => childQG.ParentQG) // 子 QuestionGroup 实体中的 ParentQG 外键
|
||||
.IsRequired(false) // ParentQG 是可空的,因为根题组没有父级
|
||||
.OnDelete(DeleteBehavior.Restrict); // 或者 SetNull, Cascade。Restrict 更安全,避免意外删除整个分支。
|
||||
// 如果选择 SetNull,删除父组时子组的 ParentQG 会变为 NULL,它们就成了新的根组。
|
||||
// 如果选择 Cascade,删除父组会递归删除所有子组。根据业务逻辑选择。
|
||||
// 这里我选择了 Restrict 作为默认安全选项。
|
||||
}
|
||||
}
|
||||
}
|
@@ -30,18 +30,13 @@ namespace TechHelper.Context.Configuration
|
||||
.HasColumnName("student_id")
|
||||
.IsRequired();
|
||||
|
||||
// AttemptNumber
|
||||
// 注意:如果 AttemptNumber 应该是一个递增的数字,Guid 可能不是最合适的类型。
|
||||
// 但根据你的定义,这里按 Guid 类型配置。
|
||||
builder.Property(s => s.AttemptNumber)
|
||||
.HasColumnName("attempt_number")
|
||||
.IsRequired();
|
||||
|
||||
// SubmissionTime
|
||||
builder.Property(s => s.SubmissionTime)
|
||||
.HasColumnName("submission_time"); // 没有 [Required] 属性,所以可以是可空的
|
||||
|
||||
// OverallGrade
|
||||
builder.Property(s => s.OverallGrade)
|
||||
.HasColumnName("overall_grade")
|
||||
.HasPrecision(5, 2); // 应用精度设置
|
||||
@@ -51,59 +46,45 @@ namespace TechHelper.Context.Configuration
|
||||
.HasColumnName("overall_feedback");
|
||||
|
||||
// GradedBy (现为 Guid? 类型)
|
||||
builder.Property(s => s.GradedBy)
|
||||
.HasColumnName("graded_by"); // 作为可空外键,不需要 IsRequired()
|
||||
builder.Property(s => s.GraderId)
|
||||
.HasColumnName("graded_by");
|
||||
|
||||
|
||||
// GradedAt
|
||||
builder.Property(s => s.GradedAt)
|
||||
.HasColumnName("graded_at");
|
||||
|
||||
// IsDeleted
|
||||
|
||||
builder.Property(s => s.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
// Status (枚举作为字符串存储)
|
||||
builder.Property(s => s.Status)
|
||||
.HasColumnName("status")
|
||||
.IsRequired()
|
||||
.HasConversion<string>() // <--- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(15); // <--- 应用最大长度
|
||||
.HasMaxLength(15);
|
||||
|
||||
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 Submission 到 Assignment 的关系 (多对一)
|
||||
// 一个 Submission 属于一个 Assignment。
|
||||
builder.HasOne(s => s.Assignment) // 当前 Submission 有一个 Assignment
|
||||
.WithMany(a => a.Submissions) // 那个 Assignment 可以有多个 Submission
|
||||
.HasForeignKey(s => s.AssignmentId) // 外键是 Submission.AssignmentId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 Submission 也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 Submission 到 User (Student) 的关系 (多对一)
|
||||
// 一个 Submission 由一个 User (Student) 提交。
|
||||
|
||||
builder.HasOne(s => s.Student) // 当前 Submission 有一个 Student (User)
|
||||
.WithMany(u => u.SubmissionsAsStudent) // 那个 User (Student) 可以有多个 Submission
|
||||
.HasForeignKey(s => s.StudentId) // 外键是 Submission.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (Student) 被删除时,如果还有其提交的 Submission,则会阻止删除。
|
||||
|
||||
// ---
|
||||
// 配置 Submission 到 User (Grader) 的关系 (多对一)
|
||||
// 一个 Submission 可以由一个 User (Grader) 批改 (可选)。
|
||||
builder.HasOne(s => s.Grader) // 当前 Submission 有一个 Grader (User),可以是空的
|
||||
.WithMany(u => u.GradedSubmissions) // 那个 User (Grader) 可以批改多个 Submission
|
||||
.HasForeignKey(s => s.GradedBy) // 外键是 Submission.GradedBy
|
||||
.HasForeignKey(s => s.GraderId) // 外键是 Submission.GradedBy
|
||||
.OnDelete(DeleteBehavior.SetNull); // 当 User (Grader) 被删除时,如果 GradedBy 是可空的,则将其设置为 NULL。
|
||||
// 如果 GradedBy 是不可空的,需要改为 Restrict 或 Cascade。
|
||||
|
||||
// ---
|
||||
// 配置 Submission 到 SubmissionDetail 的关系 (一对多)
|
||||
// 一个 Submission 可以有多个 SubmissionDetail。
|
||||
// 这个关系的外键配置通常在 "多" 的一方 (`SubmissionDetail` 实体) 进行。
|
||||
|
||||
builder.HasMany(s => s.SubmissionDetails) // 当前 Submission 有多个 SubmissionDetail
|
||||
.WithOne(sd => sd.Submission); // 每一个 SubmissionDetail 都有一个 Submission
|
||||
// .HasForeignKey(sd => sd.SubmissionId); // 外键的配置应在 `SubmissionDetailConfiguration` 中进行
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,94 +8,65 @@ namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<SubmissionDetail> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
// 将此实体映射到数据库中名为 "submission_details" 的表。
|
||||
builder.ToTable("submission_details");
|
||||
|
||||
// 2. 设置主键
|
||||
// 将 Id 属性设置为主键。
|
||||
builder.HasKey(sd => sd.Id);
|
||||
|
||||
// 3. 配置列名、必需性、精度及其他属性
|
||||
|
||||
// Id 属性对应的数据库列名为 "id"。
|
||||
builder.Property(sd => sd.Id)
|
||||
.HasColumnName("id");
|
||||
|
||||
// SubmissionId 属性对应的数据库列名为 "submission_id",并设置为必需字段。
|
||||
builder.Property(sd => sd.SubmissionId)
|
||||
.HasColumnName("submission_id")
|
||||
.IsRequired();
|
||||
|
||||
// StudentId 属性对应的数据库列名为 "student_id",并设置为必需字段。
|
||||
// 此外键指向 User 实体,代表提交该详情的学生。
|
||||
builder.Property(sd => sd.StudentId)
|
||||
.HasColumnName("student_id")
|
||||
.IsRequired();
|
||||
|
||||
// AssignmentQuestionId 属性对应的数据库列名为 "assignment_question_id",并设置为必需字段。
|
||||
builder.Property(sd => sd.AssignmentQuestionId)
|
||||
.HasColumnName("assignment_question_id")
|
||||
.IsRequired();
|
||||
|
||||
// StudentAnswer 属性对应的数据库列名为 "student_answer"。
|
||||
builder.Property(sd => sd.StudentAnswer)
|
||||
.HasColumnName("student_answer"); // string 默认可空
|
||||
|
||||
// IsCorrect 属性对应的数据库列名为 "is_correct"。
|
||||
builder.Property(sd => sd.IsCorrect)
|
||||
.HasColumnName("is_correct"); // bool? 默认可空
|
||||
|
||||
// PointsAwarded 属性对应的数据库列名为 "points_awarded",并设置精度。
|
||||
builder.Property(sd => sd.PointsAwarded)
|
||||
.HasColumnName("points_awarded")
|
||||
.HasPrecision(5, 2); // 应用 [Precision(5, 2)] 设置
|
||||
|
||||
// TeacherFeedback 属性对应的数据库列名为 "teacher_feedback"。
|
||||
builder.Property(sd => sd.TeacherFeedback)
|
||||
.HasColumnName("teacher_feedback"); // string 默认可空
|
||||
|
||||
// CreatedAt 属性对应的数据库列名为 "created_at",设置为必需字段,并在添加时自动生成值。
|
||||
builder.Property(sd => sd.CreatedAt)
|
||||
.HasColumnName("created_at")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd(); // 在实体首次保存时自动设置值
|
||||
|
||||
// UpdatedAt 属性对应的数据库列名为 "updated_at",设置为必需字段,并在添加或更新时自动生成值,同时作为并发令牌。
|
||||
builder.Property(sd => sd.UpdatedAt)
|
||||
.HasColumnName("updated_at")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate() // 在实体添加或更新时自动设置值
|
||||
.IsConcurrencyToken(); // 用作乐观并发控制,防止同时修改同一记录
|
||||
|
||||
// IsDeleted 属性对应的数据库列名为 "deleted",并设置默认值为 false。
|
||||
|
||||
builder.Property(sd => sd.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 常用作软删除标记
|
||||
.HasDefaultValue(false);
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 SubmissionDetail 到 Submission 的关系 (多对一)
|
||||
// 一个 SubmissionDetail 记录属于一个 Submission。
|
||||
builder.HasOne(sd => sd.Submission) // 当前 SubmissionDetail 有一个 Submission
|
||||
.WithMany(s => s.SubmissionDetails) // 那个 Submission 可以有多个 SubmissionDetail 记录
|
||||
.HasForeignKey(sd => sd.SubmissionId) // 外键是 SubmissionDetail.SubmissionId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Submission 被删除时,相关的 SubmissionDetail 记录也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 SubmissionDetail 到 User (作为 Student) 的关系 (多对一)
|
||||
// 一个 SubmissionDetail 记录与一个 User (提交该详情的学生) 相关联。
|
||||
// 假设 `User` 实体中有一个名为 `SubmissionDetailsAsStudent` 的 `ICollection<SubmissionDetail>` 集合属性。
|
||||
builder.HasOne(sd => sd.User) // 当前 SubmissionDetail 有一个 User (作为学生)
|
||||
builder.HasOne(sd => sd.Student) // 当前 SubmissionDetail 有一个 User (作为学生)
|
||||
.WithMany(u => u.SubmissionDetails)
|
||||
.HasForeignKey(sd => sd.StudentId) // 外键是 SubmissionDetail.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (学生) 被删除时,如果他/她还有提交详情,则会阻止删除。
|
||||
// 这是一个更安全的选择,以防止意外数据丢失。
|
||||
|
||||
// ---
|
||||
// 配置 SubmissionDetail 到 AssignmentQuestion 的关系 (多对一)
|
||||
// 一个 SubmissionDetail 记录对应一个 AssignmentQuestion。
|
||||
builder.HasOne(sd => sd.AssignmentQuestion) // 当前 SubmissionDetail 有一个 AssignmentQuestion
|
||||
.WithMany(aq => aq.SubmissionDetails) // 那个 AssignmentQuestion 可以有多个 SubmissionDetail 记录
|
||||
.HasForeignKey(sd => sd.AssignmentQuestionId) // 外键是 SubmissionDetail.AssignmentQuestionId
|
||||
|
@@ -8,14 +8,8 @@ namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<User> builder)
|
||||
{
|
||||
// 映射到表名:如果 User 类上没有 [Table("users")],默认是 "AspNetUsers"。
|
||||
// 显式指定可以确保你的数据库表名和你期望的一致。
|
||||
builder.ToTable("AspNetUsers");
|
||||
|
||||
// IdentityUser 的 Id 属性和其他标准属性(如 UserName, Email 等)
|
||||
// 大多由 IdentityDbContext 自动处理,通常不需要在这里显式配置主键或默认列。
|
||||
|
||||
// 配置自定义属性
|
||||
builder.Property(u => u.RefreshToken)
|
||||
.HasColumnName("refresh_token");
|
||||
|
||||
@@ -24,11 +18,8 @@ namespace TechHelper.Context.Configuration
|
||||
|
||||
builder.Property(u => u.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 软删除标记,默认 false
|
||||
.HasDefaultValue(false);
|
||||
|
||||
// 配置导航属性 (User 作为关系的“一”或“主”方)
|
||||
|
||||
// User 作为老师,与 ClassTeacher 的关系 (一对多)
|
||||
builder.HasMany(u => u.TaughtClassesLink) // 一个 User (老师) 可以教授多个班级
|
||||
.WithOne(ct => ct.Teacher) // 一个 ClassTeacher 记录对应一个 Teacher
|
||||
.HasForeignKey(ct => ct.TeacherId) // 外键在 ClassTeacher.TeacherId
|
||||
@@ -43,20 +34,17 @@ namespace TechHelper.Context.Configuration
|
||||
// User 作为创建者,与 Question 的关系 (一对多)
|
||||
builder.HasMany(u => u.CreatedQuestions) // 一个 User 可以创建多个题目
|
||||
.WithOne(q => q.Creator) // 一个 Question 对应一个 Creator
|
||||
.HasForeignKey(q => q.CreatedBy) // 外键在 Question.CreatedBy
|
||||
.HasForeignKey(q => q.CreatorId) // 外键在 Question.CreatedBy
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有题目,则不允许删除
|
||||
|
||||
// User 作为创建者,与 Assignment 的关系 (一对多)
|
||||
builder.HasMany(u => u.CreatedAssignments) // 一个 User 可以创建多个作业
|
||||
.WithOne(a => a.Creator) // 一个 Assignment 对应一个 Creator
|
||||
.HasForeignKey(a => a.CreatedBy) // 外键在 Assignment.CreatedBy
|
||||
.HasForeignKey(a => a.CreatorId) // 外键在 Assignment.CreatedBy
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有作业,则不允许删除
|
||||
|
||||
// User 作为学生,与 SubmissionDetail 的关系 (一对多)
|
||||
// 尽管 SubmissionDetail 也可以通过 Submission 间接关联到 User,
|
||||
// 但这里提供了直接访问的导航属性,以方便直接查询学生的所有作答详情。
|
||||
builder.HasMany(u => u.SubmissionDetails) // 一个 User (学生) 可以有多个提交详情记录
|
||||
.WithOne(sd => sd.User) // 一个 SubmissionDetail 对应一个 User (学生)
|
||||
.WithOne(sd => sd.Student) // 一个 SubmissionDetail 对应一个 User (学生)
|
||||
.HasForeignKey(sd => sd.StudentId) // 外键在 SubmissionDetail.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果学生有提交详情,则不允许删除
|
||||
|
||||
@@ -69,7 +57,7 @@ namespace TechHelper.Context.Configuration
|
||||
// User 作为批改者,与 Submission 的关系 (一对多)
|
||||
builder.HasMany(u => u.GradedSubmissions) // 一个 User (批改者) 可以批改多个提交
|
||||
.WithOne(s => s.Grader) // 一个 Submission 对应一个 Grader
|
||||
.HasForeignKey(s => s.GradedBy) // 外键在 Submission.GradedBy
|
||||
.HasForeignKey(s => s.GraderId) // 外键在 Submission.GradedBy
|
||||
.OnDelete(DeleteBehavior.SetNull); // 因为 GradedBy 是可空的,所以批改者删除时,设为 NULL
|
||||
}
|
||||
}
|
||||
|
@@ -28,9 +28,13 @@ namespace TechHelper.Server.Controllers
|
||||
|
||||
[HttpPost("add")]
|
||||
public async Task<IActionResult> AddExam(
|
||||
[FromBody] ExamDto examDto)
|
||||
[FromBody] AssignmentDto examDto)
|
||||
{
|
||||
var result = await _examService.AddAsync(examDto);
|
||||
var user = await _userManager.FindByEmailAsync(User.Identity?.Name ?? "");
|
||||
if(user == null) return BadRequest("无效的用户");
|
||||
|
||||
examDto.CreatorId = user.Id;
|
||||
var result = await _examService.CreateExamAsync(examDto);
|
||||
if (result.Status)
|
||||
{
|
||||
return Ok(result);
|
||||
@@ -63,7 +67,7 @@ namespace TechHelper.Server.Controllers
|
||||
|
||||
|
||||
|
||||
var result = await _examService.GetAllExamPreview(userid.Id);
|
||||
var result = await _examService.GetAllExamPreviewsAsync(userid.Id);
|
||||
|
||||
if (result.Status)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,93 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||
|
||||
namespace TechHelper.Server.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class assignmentnot_required : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("02a808ba-bd16-4f90-bf2b-0bc42f767e00"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("9e526681-e57e-46b5-a01c-5731b27bfc4a"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("dfdfb884-4063-4161-84e0-9c225f4e883c"));
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "assignment",
|
||||
table: "assignment_group",
|
||||
type: "char(36)",
|
||||
nullable: true,
|
||||
collation: "ascii_general_ci",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "char(36)")
|
||||
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "AspNetRoles",
|
||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ new Guid("b2e087e6-ea32-46c4-aeb3-09b936cd0cf4"), null, "Teacher", "TEACHER" },
|
||||
{ new Guid("ba33e047-8354-4f2c-b8b1-1f46441c28fc"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("d4b41bc3-612e-49dd-aeda-6a98ea0e4e68"), null, "Student", "STUDENT" }
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("b2e087e6-ea32-46c4-aeb3-09b936cd0cf4"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("ba33e047-8354-4f2c-b8b1-1f46441c28fc"));
|
||||
|
||||
migrationBuilder.DeleteData(
|
||||
table: "AspNetRoles",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("d4b41bc3-612e-49dd-aeda-6a98ea0e4e68"));
|
||||
|
||||
migrationBuilder.AlterColumn<Guid>(
|
||||
name: "assignment",
|
||||
table: "assignment_group",
|
||||
type: "char(36)",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
collation: "ascii_general_ci",
|
||||
oldClrType: typeof(Guid),
|
||||
oldType: "char(36)",
|
||||
oldNullable: true)
|
||||
.OldAnnotation("Relational:Collation", "ascii_general_ci");
|
||||
|
||||
migrationBuilder.InsertData(
|
||||
table: "AspNetRoles",
|
||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ new Guid("02a808ba-bd16-4f90-bf2b-0bc42f767e00"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("9e526681-e57e-46b5-a01c-5731b27bfc4a"), null, "Student", "STUDENT" },
|
||||
{ new Guid("dfdfb884-4063-4161-84e0-9c225f4e883c"), null, "Teacher", "TEACHER" }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,7 +12,7 @@ using TechHelper.Context;
|
||||
namespace TechHelper.Server.Migrations
|
||||
{
|
||||
[DbContext(typeof(ApplicationContext))]
|
||||
[Migration("20250610025325_init")]
|
||||
[Migration("20250619070929_init")]
|
||||
partial class init
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -36,7 +36,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
b.Property<Guid>("CreatorId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
@@ -53,9 +53,12 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<string>("SubjectArea")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext")
|
||||
b.Property<float>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("score");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<string>("Title")
|
||||
@@ -64,8 +67,8 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("varchar(255)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.Property<float?>("TotalPoints")
|
||||
.HasColumnType("float")
|
||||
b.Property<byte>("TotalQuestions")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
@@ -77,7 +80,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
b.HasIndex("CreatorId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
@@ -151,61 +154,6 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("assignment_class", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<Guid?>("AssignmentId")
|
||||
.IsRequired()
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("assignment");
|
||||
|
||||
b.Property<string>("Descript")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("descript");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<byte>("Number")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<Guid?>("ParentGroup")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_group");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.Property<float?>("TotalPoints")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<bool>("ValidQuestionGroup")
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("valid_question_group");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignmentId");
|
||||
|
||||
b.HasIndex("ParentGroup");
|
||||
|
||||
b.ToTable("assignment_group", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -221,6 +169,10 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<byte>("Index")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_number");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
@@ -231,10 +183,6 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("question_id");
|
||||
|
||||
b.Property<byte>("QuestionNumber")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_number");
|
||||
|
||||
b.Property<float?>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("score");
|
||||
@@ -248,6 +196,61 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("assignment_questions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<Guid?>("AssignmentId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("assignment");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("descript");
|
||||
|
||||
b.Property<byte>("Index")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<byte>("Layout")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("layout");
|
||||
|
||||
b.Property<Guid?>("ParentGroupId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_group");
|
||||
|
||||
b.Property<float?>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignmentId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ParentGroupId");
|
||||
|
||||
b.ToTable("assignment_group", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -337,9 +340,8 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("teacher_id");
|
||||
|
||||
b.Property<string>("SubjectTaught")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext")
|
||||
b.Property<byte>("SubjectTaught")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_taught");
|
||||
|
||||
b.HasKey("ClassId", "TeacherId");
|
||||
@@ -349,6 +351,72 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("class_teachers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<Guid>("LessonID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LessonID");
|
||||
|
||||
b.ToTable("key_point");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<Guid>("TextbookID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TextbookID");
|
||||
|
||||
b.ToTable("lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.LessonQuestion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("LessonID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Question")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LessonID");
|
||||
|
||||
b.ToTable("lesson_question");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -356,8 +424,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("CorrectAnswer")
|
||||
.IsRequired()
|
||||
b.Property<string>("Answer")
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("correct_answer");
|
||||
@@ -369,53 +436,75 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<DateTime>("CreatedAt"));
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
b.Property<Guid>("CreatorId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
b.Property<string>("DifficultyLevel")
|
||||
.IsRequired()
|
||||
b.Property<byte>("DifficultyLevel")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("varchar(10)")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("difficulty_level");
|
||||
|
||||
b.Property<byte>("GroupState")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("group_state");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<string>("QuestionText")
|
||||
b.Property<Guid?>("KeyPointId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("key_point");
|
||||
|
||||
b.Property<Guid?>("LessonId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("lesson");
|
||||
|
||||
b.Property<string>("Options")
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("options");
|
||||
|
||||
b.Property<Guid?>("ParentQuestionId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_question_group_id");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("question_text");
|
||||
|
||||
b.Property<string>("QuestionType")
|
||||
.IsRequired()
|
||||
b.Property<byte>("Type")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_type");
|
||||
|
||||
b.Property<string>("SubjectArea")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("varchar(100)")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("updated_at");
|
||||
|
||||
b.Property<bool>("ValidQuestion")
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("valid_question");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
b.HasIndex("CreatorId");
|
||||
|
||||
b.HasIndex("KeyPointId");
|
||||
|
||||
b.HasIndex("LessonId");
|
||||
|
||||
b.HasIndex("ParentQuestionId");
|
||||
|
||||
b.HasIndex("Title")
|
||||
.HasAnnotation("MySql:IndexPrefixLength", new[] { 20 });
|
||||
|
||||
b.ToTable("questions", (string)null);
|
||||
});
|
||||
@@ -439,7 +528,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("graded_at");
|
||||
|
||||
b.Property<Guid?>("GradedBy")
|
||||
b.Property<Guid?>("GraderId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("graded_by");
|
||||
|
||||
@@ -459,10 +548,9 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("overall_grade");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
b.Property<int>("Status")
|
||||
.HasMaxLength(15)
|
||||
.HasColumnType("varchar(15)")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<Guid>("StudentId")
|
||||
@@ -477,7 +565,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasIndex("AssignmentId");
|
||||
|
||||
b.HasIndex("GradedBy");
|
||||
b.HasIndex("GraderId");
|
||||
|
||||
b.HasIndex("StudentId");
|
||||
|
||||
@@ -552,6 +640,30 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("submission_details", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Textbook", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<byte>("Grade")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<byte>("Publisher")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("textbook");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -662,19 +774,19 @@ namespace TechHelper.Server.Migrations
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = new Guid("9e526681-e57e-46b5-a01c-5731b27bfc4a"),
|
||||
Id = new Guid("895d8f32-714e-4a14-bd97-8fa262b83172"),
|
||||
Name = "Student",
|
||||
NormalizedName = "STUDENT"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("dfdfb884-4063-4161-84e0-9c225f4e883c"),
|
||||
Id = new Guid("d182c396-c656-42da-965a-d93c17a1f74f"),
|
||||
Name = "Teacher",
|
||||
NormalizedName = "TEACHER"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("02a808ba-bd16-4f90-bf2b-0bc42f767e00"),
|
||||
Id = new Guid("4e65fab9-3315-4474-b92c-bdab5a617e65"),
|
||||
Name = "Administrator",
|
||||
NormalizedName = "ADMINISTRATOR"
|
||||
});
|
||||
@@ -787,7 +899,7 @@ namespace TechHelper.Server.Migrations
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "Creator")
|
||||
.WithMany()
|
||||
.HasForeignKey("CreatedBy")
|
||||
.HasForeignKey("CreatorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
@@ -828,27 +940,9 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Class");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Assignment", "Assignment")
|
||||
.WithMany("AssignmentGroups")
|
||||
.HasForeignKey("AssignmentId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Entities.Contracts.AssignmentGroup", "ParentAssignmentGroup")
|
||||
.WithMany("ChildAssignmentGroups")
|
||||
.HasForeignKey("ParentGroup")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Assignment");
|
||||
|
||||
b.Navigation("ParentAssignmentGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.AssignmentGroup", "AssignmentGroup")
|
||||
b.HasOne("Entities.Contracts.AssignmentStruct", "AssignmentGroup")
|
||||
.WithMany("AssignmentQuestions")
|
||||
.HasForeignKey("AssignmentGroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
@@ -865,6 +959,22 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Question");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Assignment", "Assignment")
|
||||
.WithOne("ExamStruct")
|
||||
.HasForeignKey("Entities.Contracts.AssignmentStruct", "AssignmentId");
|
||||
|
||||
b.HasOne("Entities.Contracts.AssignmentStruct", "ParentGroup")
|
||||
.WithMany("ChildrenGroups")
|
||||
.HasForeignKey("ParentGroupId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Assignment");
|
||||
|
||||
b.Navigation("ParentGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "HeadTeacher")
|
||||
@@ -914,15 +1024,69 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Teacher");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("KeyPoints")
|
||||
.HasForeignKey("LessonID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Textbook", "Textbook")
|
||||
.WithMany("Lessons")
|
||||
.HasForeignKey("TextbookID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Textbook");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.LessonQuestion", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("LessonQuestions")
|
||||
.HasForeignKey("LessonID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "Creator")
|
||||
.WithMany("CreatedQuestions")
|
||||
.HasForeignKey("CreatedBy")
|
||||
.HasForeignKey("CreatorId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Entities.Contracts.KeyPoint", "KeyPoint")
|
||||
.WithMany("Questions")
|
||||
.HasForeignKey("KeyPointId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("Questions")
|
||||
.HasForeignKey("LessonId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.Question", "ParentQuestion")
|
||||
.WithMany("ChildrenQuestion")
|
||||
.HasForeignKey("ParentQuestionId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("KeyPoint");
|
||||
|
||||
b.Navigation("Lesson");
|
||||
|
||||
b.Navigation("ParentQuestion");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Submission", b =>
|
||||
@@ -935,7 +1099,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "Grader")
|
||||
.WithMany("GradedSubmissions")
|
||||
.HasForeignKey("GradedBy")
|
||||
.HasForeignKey("GraderId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "Student")
|
||||
@@ -959,7 +1123,7 @@ namespace TechHelper.Server.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "User")
|
||||
b.HasOne("Entities.Contracts.User", "Student")
|
||||
.WithMany("SubmissionDetails")
|
||||
.HasForeignKey("StudentId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
@@ -973,9 +1137,9 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.Navigation("AssignmentQuestion");
|
||||
|
||||
b.Navigation("Submission");
|
||||
b.Navigation("Student");
|
||||
|
||||
b.Navigation("User");
|
||||
b.Navigation("Submission");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
@@ -1035,23 +1199,24 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.Navigation("AssignmentClasses");
|
||||
|
||||
b.Navigation("AssignmentGroups");
|
||||
b.Navigation("ExamStruct")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Submissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildAssignmentGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.Navigation("SubmissionDetails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildrenGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.Navigation("AssignmentClasses");
|
||||
@@ -1061,9 +1226,25 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("ClassTeachers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.Navigation("Questions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.Navigation("KeyPoints");
|
||||
|
||||
b.Navigation("LessonQuestions");
|
||||
|
||||
b.Navigation("Questions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildrenQuestion");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Submission", b =>
|
||||
@@ -1071,6 +1252,11 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("SubmissionDetails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Textbook", b =>
|
||||
{
|
||||
b.Navigation("Lessons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.User", b =>
|
||||
{
|
||||
b.Navigation("CreatedAssignments");
|
@@ -77,6 +77,23 @@ namespace TechHelper.Server.Migrations
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "textbook",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
Grade = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
Title = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
Publisher = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
SubjectArea = table.Column<byte>(type: "tinyint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_textbook", x => x.Id);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "AspNetRoleClaims",
|
||||
columns: table => new
|
||||
@@ -207,10 +224,10 @@ namespace TechHelper.Server.Migrations
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
description = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
subject_area = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
subject_area = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
due_date = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
total_points = table.Column<float>(type: "float", nullable: true),
|
||||
total_points = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
score = table.Column<float>(type: "float", nullable: false),
|
||||
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
updated_at = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||
@@ -263,36 +280,25 @@ namespace TechHelper.Server.Migrations
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "questions",
|
||||
name: "lesson",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
question_text = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
Title = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
question_type = table.Column<string>(type: "varchar(20)", maxLength: 20, nullable: false)
|
||||
Description = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
correct_answer = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
difficulty_level = table.Column<string>(type: "varchar(10)", maxLength: 10, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
subject_area = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
updated_at = table.Column<DateTime>(type: "datetime(6)", rowVersion: true, nullable: false),
|
||||
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false),
|
||||
valid_question = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
TextbookID = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_questions", x => x.id);
|
||||
table.PrimaryKey("PK_lesson", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_questions_AspNetUsers_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "AspNetUsers",
|
||||
name: "FK_lesson_textbook_TextbookID",
|
||||
column: x => x.TextbookID,
|
||||
principalTable: "textbook",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
@@ -326,16 +332,16 @@ namespace TechHelper.Server.Migrations
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
assignment = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
assignment = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
title = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
descript = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
layout = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
total_points = table.Column<float>(type: "float", nullable: true),
|
||||
number = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
parent_group = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false),
|
||||
valid_question_group = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -350,8 +356,7 @@ namespace TechHelper.Server.Migrations
|
||||
name: "FK_assignment_group_assignments_assignment",
|
||||
column: x => x.assignment,
|
||||
principalTable: "assignments",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
principalColumn: "id");
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
@@ -370,8 +375,7 @@ namespace TechHelper.Server.Migrations
|
||||
graded_by = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
graded_at = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false),
|
||||
status = table.Column<string>(type: "varchar(15)", maxLength: 15, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
status = table.Column<int>(type: "int", maxLength: 15, nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -457,8 +461,7 @@ namespace TechHelper.Server.Migrations
|
||||
{
|
||||
class_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
teacher_id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
subject_taught = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4")
|
||||
subject_taught = table.Column<byte>(type: "tinyint unsigned", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
@@ -478,6 +481,102 @@ namespace TechHelper.Server.Migrations
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "key_point",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
Key = table.Column<string>(type: "varchar(255)", maxLength: 255, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
LessonID = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_key_point", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_key_point_lesson_LessonID",
|
||||
column: x => x.LessonID,
|
||||
principalTable: "lesson",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "lesson_question",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
Question = table.Column<string>(type: "longtext", nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
LessonID = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_lesson_question", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_lesson_question_lesson_LessonID",
|
||||
column: x => x.LessonID,
|
||||
principalTable: "lesson",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "questions",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
question_text = table.Column<string>(type: "longtext", maxLength: 65535, nullable: false)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
correct_answer = table.Column<string>(type: "longtext", maxLength: 65535, nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
question_type = table.Column<byte>(type: "tinyint unsigned", maxLength: 20, nullable: false),
|
||||
difficulty_level = table.Column<byte>(type: "tinyint unsigned", maxLength: 10, nullable: false),
|
||||
subject_area = table.Column<byte>(type: "tinyint unsigned", maxLength: 100, nullable: false),
|
||||
group_state = table.Column<byte>(type: "tinyint unsigned", nullable: false),
|
||||
options = table.Column<string>(type: "longtext", nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||
key_point = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
lesson = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
parent_question_group_id = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||
created_by = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
created_at = table.Column<DateTime>(type: "datetime(6)", nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
updated_at = table.Column<DateTime>(type: "datetime(6)", rowVersion: true, nullable: false),
|
||||
deleted = table.Column<bool>(type: "tinyint(1)", nullable: false, defaultValue: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_questions", x => x.id);
|
||||
table.ForeignKey(
|
||||
name: "FK_questions_AspNetUsers_created_by",
|
||||
column: x => x.created_by,
|
||||
principalTable: "AspNetUsers",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_questions_key_point_key_point",
|
||||
column: x => x.key_point,
|
||||
principalTable: "key_point",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_questions_lesson_lesson",
|
||||
column: x => x.lesson,
|
||||
principalTable: "lesson",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
table.ForeignKey(
|
||||
name: "FK_questions_questions_parent_question_group_id",
|
||||
column: x => x.parent_question_group_id,
|
||||
principalTable: "questions",
|
||||
principalColumn: "id",
|
||||
onDelete: ReferentialAction.SetNull);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "assignment_questions",
|
||||
columns: table => new
|
||||
@@ -556,9 +655,9 @@ namespace TechHelper.Server.Migrations
|
||||
columns: new[] { "Id", "ConcurrencyStamp", "Name", "NormalizedName" },
|
||||
values: new object[,]
|
||||
{
|
||||
{ new Guid("02a808ba-bd16-4f90-bf2b-0bc42f767e00"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("9e526681-e57e-46b5-a01c-5731b27bfc4a"), null, "Student", "STUDENT" },
|
||||
{ new Guid("dfdfb884-4063-4161-84e0-9c225f4e883c"), null, "Teacher", "TEACHER" }
|
||||
{ new Guid("4e65fab9-3315-4474-b92c-bdab5a617e65"), null, "Administrator", "ADMINISTRATOR" },
|
||||
{ new Guid("895d8f32-714e-4a14-bd97-8fa262b83172"), null, "Student", "STUDENT" },
|
||||
{ new Guid("d182c396-c656-42da-965a-d93c17a1f74f"), null, "Teacher", "TEACHER" }
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
@@ -611,7 +710,8 @@ namespace TechHelper.Server.Migrations
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_assignment_group_assignment",
|
||||
table: "assignment_group",
|
||||
column: "assignment");
|
||||
column: "assignment",
|
||||
unique: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_assignment_group_parent_group",
|
||||
@@ -653,11 +753,47 @@ namespace TechHelper.Server.Migrations
|
||||
table: "classes",
|
||||
column: "head_teacher_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_key_point_LessonID",
|
||||
table: "key_point",
|
||||
column: "LessonID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_lesson_TextbookID",
|
||||
table: "lesson",
|
||||
column: "TextbookID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_lesson_question_LessonID",
|
||||
table: "lesson_question",
|
||||
column: "LessonID");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_questions_created_by",
|
||||
table: "questions",
|
||||
column: "created_by");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_questions_key_point",
|
||||
table: "questions",
|
||||
column: "key_point");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_questions_lesson",
|
||||
table: "questions",
|
||||
column: "lesson");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_questions_parent_question_group_id",
|
||||
table: "questions",
|
||||
column: "parent_question_group_id");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_questions_question_text",
|
||||
table: "questions",
|
||||
column: "question_text")
|
||||
.Annotation("MySql:IndexPrefixLength", new[] { 20 });
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_submission_details_assignment_question_id",
|
||||
table: "submission_details",
|
||||
@@ -719,6 +855,9 @@ namespace TechHelper.Server.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "class_teachers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "lesson_question");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "submission_details");
|
||||
|
||||
@@ -743,8 +882,17 @@ namespace TechHelper.Server.Migrations
|
||||
migrationBuilder.DropTable(
|
||||
name: "assignments");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "key_point");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "AspNetUsers");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "lesson");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "textbook");
|
||||
}
|
||||
}
|
||||
}
|
@@ -33,7 +33,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
b.Property<Guid>("CreatorId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
@@ -50,9 +50,12 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<string>("SubjectArea")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext")
|
||||
b.Property<float>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("score");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<string>("Title")
|
||||
@@ -61,8 +64,8 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("varchar(255)")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.Property<float?>("TotalPoints")
|
||||
.HasColumnType("float")
|
||||
b.Property<byte>("TotalQuestions")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
@@ -74,7 +77,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
b.HasIndex("CreatorId");
|
||||
|
||||
b.HasIndex("UserId");
|
||||
|
||||
@@ -148,60 +151,6 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("assignment_class", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<Guid?>("AssignmentId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("assignment");
|
||||
|
||||
b.Property<string>("Descript")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("descript");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<byte>("Number")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<Guid?>("ParentGroup")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_group");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.Property<float?>("TotalPoints")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<bool>("ValidQuestionGroup")
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("valid_question_group");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignmentId");
|
||||
|
||||
b.HasIndex("ParentGroup");
|
||||
|
||||
b.ToTable("assignment_group", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -217,6 +166,10 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("created_at");
|
||||
|
||||
b.Property<byte>("Index")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_number");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
@@ -227,10 +180,6 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("question_id");
|
||||
|
||||
b.Property<byte>("QuestionNumber")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_number");
|
||||
|
||||
b.Property<float?>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("score");
|
||||
@@ -244,6 +193,61 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("assignment_questions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<Guid?>("AssignmentId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("assignment");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("descript");
|
||||
|
||||
b.Property<byte>("Index")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("number");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<byte>("Layout")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("layout");
|
||||
|
||||
b.Property<Guid?>("ParentGroupId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_group");
|
||||
|
||||
b.Property<float?>("Score")
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("total_points");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("title");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AssignmentId")
|
||||
.IsUnique();
|
||||
|
||||
b.HasIndex("ParentGroupId");
|
||||
|
||||
b.ToTable("assignment_group", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -333,9 +337,8 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("teacher_id");
|
||||
|
||||
b.Property<string>("SubjectTaught")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext")
|
||||
b.Property<byte>("SubjectTaught")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_taught");
|
||||
|
||||
b.HasKey("ClassId", "TeacherId");
|
||||
@@ -345,6 +348,72 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("class_teachers", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Key")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.Property<Guid>("LessonID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LessonID");
|
||||
|
||||
b.ToTable("key_point");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Description")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.Property<Guid>("TextbookID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255)
|
||||
.HasColumnType("varchar(255)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("TextbookID");
|
||||
|
||||
b.ToTable("lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.LessonQuestion", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<Guid>("LessonID")
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<string>("Question")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("LessonID");
|
||||
|
||||
b.ToTable("lesson_question");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -352,8 +421,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("id");
|
||||
|
||||
b.Property<string>("CorrectAnswer")
|
||||
.IsRequired()
|
||||
b.Property<string>("Answer")
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("correct_answer");
|
||||
@@ -365,53 +433,75 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<DateTime>("CreatedAt"));
|
||||
|
||||
b.Property<Guid>("CreatedBy")
|
||||
b.Property<Guid>("CreatorId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("created_by");
|
||||
|
||||
b.Property<string>("DifficultyLevel")
|
||||
.IsRequired()
|
||||
b.Property<byte>("DifficultyLevel")
|
||||
.HasMaxLength(10)
|
||||
.HasColumnType("varchar(10)")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("difficulty_level");
|
||||
|
||||
b.Property<byte>("GroupState")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("group_state");
|
||||
|
||||
b.Property<bool>("IsDeleted")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasDefaultValue(false)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
b.Property<string>("QuestionText")
|
||||
b.Property<Guid?>("KeyPointId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("key_point");
|
||||
|
||||
b.Property<Guid?>("LessonId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("lesson");
|
||||
|
||||
b.Property<string>("Options")
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("options");
|
||||
|
||||
b.Property<Guid?>("ParentQuestionId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("parent_question_group_id");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535)
|
||||
.HasColumnType("longtext")
|
||||
.HasColumnName("question_text");
|
||||
|
||||
b.Property<string>("QuestionType")
|
||||
.IsRequired()
|
||||
b.Property<byte>("Type")
|
||||
.HasMaxLength(20)
|
||||
.HasColumnType("varchar(20)")
|
||||
.HasColumnType("tinyint unsigned")
|
||||
.HasColumnName("question_type");
|
||||
|
||||
b.Property<string>("SubjectArea")
|
||||
.IsRequired()
|
||||
.HasMaxLength(100)
|
||||
.HasColumnType("varchar(100)")
|
||||
.HasColumnName("subject_area");
|
||||
|
||||
b.Property<DateTime>("UpdatedAt")
|
||||
.IsConcurrencyToken()
|
||||
.ValueGeneratedOnAddOrUpdate()
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("updated_at");
|
||||
|
||||
b.Property<bool>("ValidQuestion")
|
||||
.HasColumnType("tinyint(1)")
|
||||
.HasColumnName("valid_question");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("CreatedBy");
|
||||
b.HasIndex("CreatorId");
|
||||
|
||||
b.HasIndex("KeyPointId");
|
||||
|
||||
b.HasIndex("LessonId");
|
||||
|
||||
b.HasIndex("ParentQuestionId");
|
||||
|
||||
b.HasIndex("Title")
|
||||
.HasAnnotation("MySql:IndexPrefixLength", new[] { 20 });
|
||||
|
||||
b.ToTable("questions", (string)null);
|
||||
});
|
||||
@@ -435,7 +525,7 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("datetime(6)")
|
||||
.HasColumnName("graded_at");
|
||||
|
||||
b.Property<Guid?>("GradedBy")
|
||||
b.Property<Guid?>("GraderId")
|
||||
.HasColumnType("char(36)")
|
||||
.HasColumnName("graded_by");
|
||||
|
||||
@@ -455,10 +545,9 @@ namespace TechHelper.Server.Migrations
|
||||
.HasColumnType("float")
|
||||
.HasColumnName("overall_grade");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.IsRequired()
|
||||
b.Property<int>("Status")
|
||||
.HasMaxLength(15)
|
||||
.HasColumnType("varchar(15)")
|
||||
.HasColumnType("int")
|
||||
.HasColumnName("status");
|
||||
|
||||
b.Property<Guid>("StudentId")
|
||||
@@ -473,7 +562,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasIndex("AssignmentId");
|
||||
|
||||
b.HasIndex("GradedBy");
|
||||
b.HasIndex("GraderId");
|
||||
|
||||
b.HasIndex("StudentId");
|
||||
|
||||
@@ -548,6 +637,30 @@ namespace TechHelper.Server.Migrations
|
||||
b.ToTable("submission_details", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Textbook", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("char(36)");
|
||||
|
||||
b.Property<byte>("Grade")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<byte>("Publisher")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<byte>("SubjectArea")
|
||||
.HasColumnType("tinyint unsigned");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.IsRequired()
|
||||
.HasColumnType("longtext");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("textbook");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.User", b =>
|
||||
{
|
||||
b.Property<Guid>("Id")
|
||||
@@ -658,19 +771,19 @@ namespace TechHelper.Server.Migrations
|
||||
b.HasData(
|
||||
new
|
||||
{
|
||||
Id = new Guid("d4b41bc3-612e-49dd-aeda-6a98ea0e4e68"),
|
||||
Id = new Guid("895d8f32-714e-4a14-bd97-8fa262b83172"),
|
||||
Name = "Student",
|
||||
NormalizedName = "STUDENT"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("b2e087e6-ea32-46c4-aeb3-09b936cd0cf4"),
|
||||
Id = new Guid("d182c396-c656-42da-965a-d93c17a1f74f"),
|
||||
Name = "Teacher",
|
||||
NormalizedName = "TEACHER"
|
||||
},
|
||||
new
|
||||
{
|
||||
Id = new Guid("ba33e047-8354-4f2c-b8b1-1f46441c28fc"),
|
||||
Id = new Guid("4e65fab9-3315-4474-b92c-bdab5a617e65"),
|
||||
Name = "Administrator",
|
||||
NormalizedName = "ADMINISTRATOR"
|
||||
});
|
||||
@@ -783,7 +896,7 @@ namespace TechHelper.Server.Migrations
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "Creator")
|
||||
.WithMany()
|
||||
.HasForeignKey("CreatedBy")
|
||||
.HasForeignKey("CreatorId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
@@ -824,26 +937,9 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Class");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Assignment", "Assignment")
|
||||
.WithMany("AssignmentGroups")
|
||||
.HasForeignKey("AssignmentId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
b.HasOne("Entities.Contracts.AssignmentGroup", "ParentAssignmentGroup")
|
||||
.WithMany("ChildAssignmentGroups")
|
||||
.HasForeignKey("ParentGroup")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Assignment");
|
||||
|
||||
b.Navigation("ParentAssignmentGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.AssignmentGroup", "AssignmentGroup")
|
||||
b.HasOne("Entities.Contracts.AssignmentStruct", "AssignmentGroup")
|
||||
.WithMany("AssignmentQuestions")
|
||||
.HasForeignKey("AssignmentGroupId")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
@@ -860,6 +956,22 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Question");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Assignment", "Assignment")
|
||||
.WithOne("ExamStruct")
|
||||
.HasForeignKey("Entities.Contracts.AssignmentStruct", "AssignmentId");
|
||||
|
||||
b.HasOne("Entities.Contracts.AssignmentStruct", "ParentGroup")
|
||||
.WithMany("ChildrenGroups")
|
||||
.HasForeignKey("ParentGroupId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Assignment");
|
||||
|
||||
b.Navigation("ParentGroup");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "HeadTeacher")
|
||||
@@ -909,15 +1021,69 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("Teacher");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("KeyPoints")
|
||||
.HasForeignKey("LessonID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Textbook", "Textbook")
|
||||
.WithMany("Lessons")
|
||||
.HasForeignKey("TextbookID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Textbook");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.LessonQuestion", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("LessonQuestions")
|
||||
.HasForeignKey("LessonID")
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Lesson");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.HasOne("Entities.Contracts.User", "Creator")
|
||||
.WithMany("CreatedQuestions")
|
||||
.HasForeignKey("CreatedBy")
|
||||
.HasForeignKey("CreatorId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Entities.Contracts.KeyPoint", "KeyPoint")
|
||||
.WithMany("Questions")
|
||||
.HasForeignKey("KeyPointId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.Lesson", "Lesson")
|
||||
.WithMany("Questions")
|
||||
.HasForeignKey("LessonId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.Question", "ParentQuestion")
|
||||
.WithMany("ChildrenQuestion")
|
||||
.HasForeignKey("ParentQuestionId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.Navigation("Creator");
|
||||
|
||||
b.Navigation("KeyPoint");
|
||||
|
||||
b.Navigation("Lesson");
|
||||
|
||||
b.Navigation("ParentQuestion");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Submission", b =>
|
||||
@@ -930,7 +1096,7 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "Grader")
|
||||
.WithMany("GradedSubmissions")
|
||||
.HasForeignKey("GradedBy")
|
||||
.HasForeignKey("GraderId")
|
||||
.OnDelete(DeleteBehavior.SetNull);
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "Student")
|
||||
@@ -954,7 +1120,7 @@ namespace TechHelper.Server.Migrations
|
||||
.OnDelete(DeleteBehavior.Cascade)
|
||||
.IsRequired();
|
||||
|
||||
b.HasOne("Entities.Contracts.User", "User")
|
||||
b.HasOne("Entities.Contracts.User", "Student")
|
||||
.WithMany("SubmissionDetails")
|
||||
.HasForeignKey("StudentId")
|
||||
.OnDelete(DeleteBehavior.Restrict)
|
||||
@@ -968,9 +1134,9 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.Navigation("AssignmentQuestion");
|
||||
|
||||
b.Navigation("Submission");
|
||||
b.Navigation("Student");
|
||||
|
||||
b.Navigation("User");
|
||||
b.Navigation("Submission");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<System.Guid>", b =>
|
||||
@@ -1030,23 +1196,24 @@ namespace TechHelper.Server.Migrations
|
||||
|
||||
b.Navigation("AssignmentClasses");
|
||||
|
||||
b.Navigation("AssignmentGroups");
|
||||
b.Navigation("ExamStruct")
|
||||
.IsRequired();
|
||||
|
||||
b.Navigation("Submissions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentGroup", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildAssignmentGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentQuestion", b =>
|
||||
{
|
||||
b.Navigation("SubmissionDetails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.AssignmentStruct", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildrenGroups");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Class", b =>
|
||||
{
|
||||
b.Navigation("AssignmentClasses");
|
||||
@@ -1056,9 +1223,25 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("ClassTeachers");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.KeyPoint", b =>
|
||||
{
|
||||
b.Navigation("Questions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Lesson", b =>
|
||||
{
|
||||
b.Navigation("KeyPoints");
|
||||
|
||||
b.Navigation("LessonQuestions");
|
||||
|
||||
b.Navigation("Questions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Question", b =>
|
||||
{
|
||||
b.Navigation("AssignmentQuestions");
|
||||
|
||||
b.Navigation("ChildrenQuestion");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Submission", b =>
|
||||
@@ -1066,6 +1249,11 @@ namespace TechHelper.Server.Migrations
|
||||
b.Navigation("SubmissionDetails");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.Textbook", b =>
|
||||
{
|
||||
b.Navigation("Lessons");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Entities.Contracts.User", b =>
|
||||
{
|
||||
b.Navigation("CreatedAssignments");
|
||||
|
@@ -11,6 +11,7 @@ using System.Text;
|
||||
using TechHelper.Features;
|
||||
using TechHelper.Services;
|
||||
using TechHelper.Server.Services;
|
||||
using TechHelper.Server.Repositories;
|
||||
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
@@ -26,7 +27,7 @@ builder.Services.AddDbContext<ApplicationContext>(options =>
|
||||
).AddUnitOfWork<ApplicationContext>()
|
||||
.AddCustomRepository<Assignment, AssignmentRepository>()
|
||||
.AddCustomRepository<AssignmentAttachment, AssignmentAttachmentRepository>()
|
||||
.AddCustomRepository<AssignmentGroup, AssignmentGroupRepository>()
|
||||
.AddCustomRepository<AssignmentStruct, AssignmentGroupRepository>()
|
||||
.AddCustomRepository<AssignmentQuestion, AssignmentQuestionRepository>()
|
||||
.AddCustomRepository<Class, ClassRepository>()
|
||||
.AddCustomRepository<ClassStudent, ClassStudentRepository>()
|
||||
@@ -85,6 +86,7 @@ builder.Services.AddScoped<IEmailSender, QEmailSender>();
|
||||
builder.Services.AddTransient<IUserRegistrationService, UserRegistrationService>();
|
||||
builder.Services.AddScoped<IClassService, ClassService>();
|
||||
builder.Services.AddScoped<IExamService, ExamService>();
|
||||
builder.Services.AddScoped<IExamRepository, ExamRepository>();
|
||||
|
||||
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
|
92
TechHelper.Server/Repositories/ExamRepository.cs
Normal file
92
TechHelper.Server/Repositories/ExamRepository.cs
Normal file
@@ -0,0 +1,92 @@
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Repository;
|
||||
|
||||
namespace TechHelper.Server.Repositories
|
||||
{
|
||||
public class ExamRepository : IExamRepository
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IRepository<Assignment> _assignmentRepo;
|
||||
private readonly IRepository<AssignmentStruct> _assignmentGroupRepo;
|
||||
private readonly IRepository<Question> _questionRepo;
|
||||
|
||||
public ExamRepository(IUnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
|
||||
_assignmentGroupRepo = _unitOfWork.GetRepository<AssignmentStruct>();
|
||||
}
|
||||
|
||||
public async Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId)
|
||||
{
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private async Task LoadSubGroupsRecursive(AssignmentStruct group)
|
||||
{
|
||||
// EF Core 已经加载了下一层,我们需要确保更深层次的加载
|
||||
var groupWithChildren = await _assignmentGroupRepo.GetFirstOrDefaultAsync(
|
||||
predicate: g => g.Id == group.Id,
|
||||
include: source => source
|
||||
.Include(g => g.ChildrenGroups.Where(cg => !cg.IsDeleted))
|
||||
.ThenInclude(cg => cg.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
.Include(g => g.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
);
|
||||
|
||||
group.ChildrenGroups = groupWithChildren.ChildrenGroups;
|
||||
group.AssignmentQuestions = groupWithChildren.AssignmentQuestions;
|
||||
|
||||
if (group.ChildrenGroups != null)
|
||||
{
|
||||
foreach (var child in group.ChildrenGroups)
|
||||
{
|
||||
await LoadSubGroupsRecursive(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Assignment>> GetExamPreviewsByUserAsync(Guid userId)
|
||||
{
|
||||
return await _assignmentRepo.GetAllAsync(
|
||||
predicate: a => a.CreatorId == userId && !a.IsDeleted);
|
||||
}
|
||||
|
||||
public async Task AddAsync(Assignment assignment)
|
||||
{
|
||||
await _assignmentRepo.InsertAsync(assignment);
|
||||
}
|
||||
|
||||
|
||||
public async Task AddAsync(QuestionGroupDto qg)
|
||||
{
|
||||
if (qg.ValidQuestionGroup)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public async Task AddAsync(AssignmentStruct assignment)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task AddAsync(AssignmentQuestion assignment)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task AddAsync(Question assignment)
|
||||
{
|
||||
}
|
||||
|
||||
public async Task AddAsync(AssignmentClass assignment)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
using Entities.Contracts;
|
||||
|
||||
namespace TechHelper.Server.Repository
|
||||
namespace TechHelper.Server.Repositories
|
||||
{
|
||||
public interface IExamRepository
|
||||
{
|
||||
@@ -23,5 +23,16 @@ namespace TechHelper.Server.Repository
|
||||
/// </summary>
|
||||
/// <param name="assignment">要添加的试卷实体。</param>
|
||||
Task AddAsync(Assignment assignment);
|
||||
|
||||
|
||||
|
||||
Task AddAsync(AssignmentStruct assignment);
|
||||
|
||||
Task AddAsync(AssignmentQuestion assignment);
|
||||
|
||||
Task AddAsync(Question assignment);
|
||||
|
||||
Task AddAsync(AssignmentClass assignment);
|
||||
|
||||
}
|
||||
}
|
@@ -5,7 +5,7 @@ using TechHelper.Context;
|
||||
|
||||
namespace TechHelper.Repository
|
||||
{
|
||||
public class AssignmentGroupRepository : Repository<AssignmentGroup>, IRepository<AssignmentGroup>
|
||||
public class AssignmentGroupRepository : Repository<AssignmentStruct>, IRepository<AssignmentStruct>
|
||||
{
|
||||
public AssignmentGroupRepository(ApplicationContext dbContext) : base(dbContext)
|
||||
{
|
||||
|
@@ -10,5 +10,10 @@ namespace TechHelper.Repository
|
||||
public AssignmentRepository(ApplicationContext dbContext) : base(dbContext)
|
||||
{
|
||||
}
|
||||
|
||||
public void THISTEST()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,96 +0,0 @@
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedDATA.Api;
|
||||
|
||||
namespace TechHelper.Server.Repository
|
||||
{
|
||||
public class ExamRepository : IExamRepository
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IRepository<Assignment> _assignmentRepo;
|
||||
private readonly IRepository<AssignmentGroup> _assignmentGroupRepo;
|
||||
private readonly IRepository<QuestionGroup> _questionGroupRepo;
|
||||
private readonly IRepository<Question> _questionRepo;
|
||||
|
||||
public ExamRepository(IUnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
|
||||
_assignmentGroupRepo = _unitOfWork.GetRepository<AssignmentGroup>();
|
||||
}
|
||||
|
||||
public async Task<Assignment?> GetFullExamByIdAsync(Guid assignmentId)
|
||||
{
|
||||
|
||||
var assignment = await _assignmentRepo.GetFirstOrDefaultAsync(
|
||||
predicate: a => a.Id == assignmentId && !a.IsDeleted,
|
||||
include: source => source
|
||||
.Include
|
||||
(a => a.AssignmentGroups.Where(ag => ag.ParentGroup == null && !ag.IsDeleted)) // 加载根题组
|
||||
.ThenInclude(ag => ag.ChildAssignmentGroups.Where(cag => !cag.IsDeleted)) // 加载子题组
|
||||
.ThenInclude(cag => cag.AssignmentQuestions.Where(aq => !aq.IsDeleted)) // 加载子题组的题目
|
||||
.ThenInclude(aq => aq.Question)
|
||||
.Include(a => a.AssignmentGroups.Where(ag => ag.ParentGroup == null && !ag.IsDeleted)) // 再次从根开始,加载题组下的题目
|
||||
.ThenInclude(ag => ag.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
);
|
||||
|
||||
if (assignment?.AssignmentGroups != null)
|
||||
{
|
||||
foreach (var rootGroup in assignment.AssignmentGroups)
|
||||
{
|
||||
await LoadSubGroupsRecursive(rootGroup);
|
||||
}
|
||||
}
|
||||
|
||||
return assignment;
|
||||
}
|
||||
|
||||
|
||||
private async Task LoadSubGroupsRecursive(AssignmentGroup group)
|
||||
{
|
||||
// EF Core 已经加载了下一层,我们需要确保更深层次的加载
|
||||
var groupWithChildren = await _assignmentGroupRepo.GetFirstOrDefaultAsync(
|
||||
predicate: g => g.Id == group.Id,
|
||||
include: source => source
|
||||
.Include(g => g.ChildAssignmentGroups.Where(cg => !cg.IsDeleted))
|
||||
.ThenInclude(cg => cg.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
.Include(g => g.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
);
|
||||
|
||||
group.ChildAssignmentGroups = groupWithChildren.ChildAssignmentGroups;
|
||||
group.AssignmentQuestions = groupWithChildren.AssignmentQuestions;
|
||||
|
||||
if (group.ChildAssignmentGroups != null)
|
||||
{
|
||||
foreach (var child in group.ChildAssignmentGroups)
|
||||
{
|
||||
await LoadSubGroupsRecursive(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Assignment>> GetExamPreviewsByUserAsync(Guid userId)
|
||||
{
|
||||
return await _assignmentRepo.GetAllAsync(
|
||||
predicate: a => a.CreatedBy == userId && !a.IsDeleted);
|
||||
}
|
||||
|
||||
public async Task AddAsync(Assignment assignment)
|
||||
{
|
||||
await _assignmentRepo.InsertAsync(assignment);
|
||||
}
|
||||
|
||||
|
||||
public async Task AddAsync(QuestionGroupDto qg)
|
||||
{
|
||||
if(qg.ValidQuestionGroup)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
TechHelper.Server/Repository/UserRepository.cs
Normal file
17
TechHelper.Server/Repository/UserRepository.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Context;
|
||||
|
||||
namespace TechHelper.Repository
|
||||
{
|
||||
public class UserRepository : Repository<User>, IRepository<User>
|
||||
{
|
||||
public UserRepository(ApplicationContext dbContext) : base(dbContext)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
@@ -1,47 +0,0 @@
|
||||
namespace TechHelper.Services
|
||||
{
|
||||
public class ApiResponse
|
||||
{
|
||||
public string Message { get; set; }
|
||||
public bool Status { get; set; }
|
||||
public object? Result { get; set; }
|
||||
|
||||
private ApiResponse(bool status, string message, object? result)
|
||||
{
|
||||
Status = status;
|
||||
Message = message;
|
||||
Result = result;
|
||||
}
|
||||
|
||||
public ApiResponse(string message, bool status = false)
|
||||
: this(status, message, null) { }
|
||||
|
||||
|
||||
public ApiResponse(bool status, object result)
|
||||
: this(status, string.Empty, result) { }
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个表示成功响应的 ApiResponse 实例。
|
||||
/// </summary>
|
||||
/// <param name="message">成功消息。</param>
|
||||
/// <param name="result">可选的返回数据。</param>
|
||||
/// <returns>ApiResponse 实例。</returns>
|
||||
public static ApiResponse Success(string message = "操作成功。", object? result = null)
|
||||
{
|
||||
return new ApiResponse(true, message, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个表示失败响应的 ApiResponse 实例。
|
||||
/// </summary>
|
||||
/// <param name="message">错误消息。</param>
|
||||
/// <param name="result">可选的错误详情或数据。</param>
|
||||
/// <returns>ApiResponse 实例。</returns>
|
||||
public static ApiResponse Error(string message = "操作失败。", object? result = null)
|
||||
{
|
||||
return new ApiResponse(false, message, result);
|
||||
}
|
||||
}
|
||||
}
|
@@ -197,7 +197,7 @@ namespace TechHelper.Services
|
||||
{
|
||||
ClassId = existingClass.Id,
|
||||
TeacherId = existingClass.Id,
|
||||
SubjectTaught = user.SubjectArea.ToString()
|
||||
SubjectTaught = user.SubjectArea
|
||||
};
|
||||
await _work.GetRepository<ClassTeacher>().InsertAsync(classTeacher);
|
||||
|
||||
|
@@ -1,56 +1,149 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using MySqlConnector;
|
||||
using Microsoft.VisualBasic;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Context;
|
||||
using TechHelper.Server.Repositories;
|
||||
using TechHelper.Services;
|
||||
using static TechHelper.Context.AutoMapperProFile;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
|
||||
public class ExamService : IExamService
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IRepository<Assignment> _assignmentRepo;
|
||||
private readonly IRepository<AssignmentGroup> _assignmentGroupRepo;
|
||||
private readonly IRepository<AssignmentQuestion> _assignmentQuestionRepo;
|
||||
private readonly IRepository<Question> _questionRepo;
|
||||
public ExamService(IUnitOfWork unitOfWork, IMapper mapper, UserManager<User> userManager)
|
||||
private readonly IExamRepository _examRepository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public ExamService(IUnitOfWork unitOfWork, IExamRepository examRepository, IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_examRepository = examRepository;
|
||||
_mapper = mapper;
|
||||
_userManager = userManager;
|
||||
|
||||
_assignmentRepo = _unitOfWork.GetRepository<Assignment>();
|
||||
_assignmentGroupRepo = _unitOfWork.GetRepository<AssignmentGroup>();
|
||||
_assignmentQuestionRepo = _unitOfWork.GetRepository<AssignmentQuestion>();
|
||||
_questionRepo = _unitOfWork.GetRepository<Question>();
|
||||
}
|
||||
|
||||
private readonly IMapper _mapper;
|
||||
private readonly UserManager<User> _userManager;
|
||||
|
||||
public async Task<ApiResponse> AddAsync(ExamDto model)
|
||||
public async Task<ApiResponse> CreateExamAsync(AssignmentDto assignmentDto)
|
||||
{
|
||||
try
|
||||
|
||||
Assignment newAssi = _mapper.Map<Assignment>(assignmentDto);
|
||||
|
||||
await _examRepository.AddAsync(newAssi);
|
||||
|
||||
|
||||
var context = _unitOfWork.GetDbContext<ApplicationContext>();
|
||||
|
||||
foreach (var entry in context.ChangeTracker.Entries())
|
||||
{
|
||||
var result = await SaveParsedExam(model);
|
||||
if (result.Status)
|
||||
if (entry.State == Microsoft.EntityFrameworkCore.EntityState.Added)
|
||||
{
|
||||
return ApiResponse.Success("保存试题成功");
|
||||
}
|
||||
else
|
||||
{
|
||||
return ApiResponse.Error($"保存试题数据失败{result.Message}");
|
||||
if(entry.Entity is Question newQues)
|
||||
{
|
||||
newQues.CreatorId = newAssi.CreatorId;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return ApiResponse.Success();
|
||||
}
|
||||
|
||||
private async void ParseStruct(AssignmentStructDto assignmentStruct, Guid ParentID)
|
||||
{
|
||||
|
||||
var newStruct = _mapper.Map<AssignmentStruct>(assignmentStruct);
|
||||
newStruct.ParentStructId = Guid.Empty == ParentID ? null : ParentID;
|
||||
await _examRepository.AddAsync(newStruct);
|
||||
|
||||
|
||||
foreach (var item in assignmentStruct.AssignmentQuestions)
|
||||
{
|
||||
return ApiResponse.Error($"保存试题数据失败: {ex.Message}");
|
||||
var newQuestion = _mapper.Map<Question>(item);
|
||||
//newQuestion.ParentQuestionId = item.ParentQuestion == null ? null : item.ParentQuestion.Id;
|
||||
await _examRepository.AddAsync(newQuestion);
|
||||
|
||||
//await ParseAssignmentQuestion(assignmentStruct, item, newQuestion);
|
||||
}
|
||||
|
||||
|
||||
foreach (var item in assignmentStruct.ChildrenGroups)
|
||||
{
|
||||
ParseStruct(item, assignmentStruct.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ParseAssignmentQuestion(AssignmentStructDto assignmentStruct, QuestionDto item, Question newQuestion)
|
||||
{
|
||||
AssignmentQuestion newAssignQues = new AssignmentQuestion();
|
||||
newAssignQues.QuestionId = newQuestion.Id;
|
||||
newAssignQues.AssignmentStructId = assignmentStruct.Id;
|
||||
newAssignQues.CreatedAt = DateTime.UtcNow;
|
||||
newAssignQues.Score = item.Score;
|
||||
await _examRepository.AddAsync(newAssignQues);
|
||||
}
|
||||
|
||||
private void SetEntityIdsAndRelations(AssignmentStruct group, Guid? assignmentId, Guid creatorId)
|
||||
{
|
||||
group.Id = Guid.NewGuid();
|
||||
group.AssignmentId = assignmentId;
|
||||
|
||||
foreach (var aq in group.AssignmentQuestions)
|
||||
{
|
||||
aq.Id = Guid.NewGuid();
|
||||
aq.AssignmentStructId = group.Id;
|
||||
aq.Question.Id = Guid.NewGuid();
|
||||
aq.Question.CreatorId = creatorId;
|
||||
aq.CreatedAt = DateTime.UtcNow;
|
||||
// ... 其他默认值
|
||||
}
|
||||
|
||||
foreach (var childGroup in group.ChildrenGroups)
|
||||
{
|
||||
// 子题组的 AssignmentId 为 null,通过 ParentGroup 关联
|
||||
SetEntityIdsAndRelations(childGroup, null, creatorId);
|
||||
childGroup.ParentStructId = group.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<AssignmentDto> GetExamByIdAsync(Guid id)
|
||||
{
|
||||
var assignment = await _examRepository.GetFullExamByIdAsync(id);
|
||||
if (assignment == null)
|
||||
{
|
||||
|
||||
throw new InvalidOperationException("");
|
||||
}
|
||||
|
||||
return _mapper.Map<AssignmentDto>(assignment);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<AssignmentDto>> GetAllExamPreviewsAsync(Guid userId)
|
||||
{
|
||||
var assignments = await _examRepository.GetExamPreviewsByUserAsync(userId);
|
||||
return _mapper.Map<IEnumerable<AssignmentDto>>(assignments);
|
||||
}
|
||||
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> AddAsync(AssignmentDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(AssignmentDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||
@@ -58,392 +151,10 @@ namespace TechHelper.Server.Services
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
Task<ApiResponse> IExamService.GetAllExamPreviewsAsync(Guid userId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await GetExamByIdAsync(id);
|
||||
return result;
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"获取试题数据失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(ExamDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<AssignmentGroup>> LoadFullGroupTree(Guid rootGroupId)
|
||||
{
|
||||
var query = @"
|
||||
WITH RECURSIVE GroupTree AS (
|
||||
SELECT
|
||||
ag.*,
|
||||
CAST(ag.`number` AS CHAR(255)) AS path
|
||||
FROM assignment_group ag
|
||||
WHERE ag.id = @rootId
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
c.*,
|
||||
CONCAT(ct.path, '.', c.`number`)
|
||||
FROM assignment_group c
|
||||
INNER JOIN GroupTree ct ON c.parent_group = ct.id
|
||||
)
|
||||
SELECT * FROM GroupTree ORDER BY path;
|
||||
";
|
||||
|
||||
// 执行查询
|
||||
var groups = await _unitOfWork.GetRepository<AssignmentGroup>()
|
||||
.FromSql(query, new MySqlParameter("rootId", rootGroupId))
|
||||
.ToListAsync();
|
||||
|
||||
// 内存中构建树结构
|
||||
var groupDict = groups.ToDictionary(g => g.Id);
|
||||
var root = groupDict[rootGroupId];
|
||||
|
||||
foreach (var group in groups)
|
||||
{
|
||||
if (group.ParentGroup != null && groupDict.TryGetValue(group.ParentGroup.Value, out var parent))
|
||||
{
|
||||
parent.ChildAssignmentGroups ??= new List<AssignmentGroup>();
|
||||
parent.ChildAssignmentGroups.Add(group);
|
||||
}
|
||||
}
|
||||
|
||||
return new List<AssignmentGroup> { root };
|
||||
}
|
||||
|
||||
public async Task LoadRecursiveAssignmentGroups(IEnumerable<AssignmentGroup> groups)
|
||||
{
|
||||
foreach (var group in groups.ToList())
|
||||
{
|
||||
|
||||
var loadedGroup = await _unitOfWork.GetRepository<AssignmentGroup>()
|
||||
.GetFirstOrDefaultAsync(
|
||||
predicate: ag => ag.Id == group.Id,
|
||||
include: source => source
|
||||
.Include(ag => ag.AssignmentQuestions.Where(aq => !aq.IsDeleted))
|
||||
.ThenInclude(aq => aq.Question)
|
||||
.Include(ag => ag.ChildAssignmentGroups)
|
||||
);
|
||||
|
||||
if (loadedGroup == null) continue;
|
||||
|
||||
group.ChildAssignmentGroups = loadedGroup.ChildAssignmentGroups;
|
||||
group.AssignmentQuestions = loadedGroup.AssignmentQuestions;
|
||||
|
||||
if (group.ChildAssignmentGroups is { Count: > 0 })
|
||||
{
|
||||
await LoadRecursiveAssignmentGroups(group.ChildAssignmentGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetExamByIdAsync(Guid assignmentId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assignment = await _unitOfWork.GetRepository<Assignment>().GetFirstOrDefaultAsync(
|
||||
predicate: a => a.Id == assignmentId && !a.IsDeleted);
|
||||
|
||||
if (assignment == null)
|
||||
{
|
||||
return ApiResponse.Error($"找不到 ID 为 {assignmentId} 的试卷。");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 获取所有相关题组和题目,并过滤掉已删除的
|
||||
var allGroups = await _unitOfWork.GetRepository<AssignmentGroup>().GetFirstOrDefaultAsync(
|
||||
predicate: ag => ag.AssignmentId == assignmentId && !ag.IsDeleted,
|
||||
include: source => source
|
||||
.Include(ag => ag.ChildAssignmentGroups)
|
||||
);
|
||||
await LoadRecursiveAssignmentGroups(allGroups.ChildAssignmentGroups);
|
||||
|
||||
if (allGroups == null || !allGroups.ChildAssignmentGroups.Any())
|
||||
{
|
||||
// 试卷存在但没有内容,返回一个空的 ExamDto
|
||||
return ApiResponse.Success("试卷没有内容。", new ExamDto
|
||||
{
|
||||
AssignmentId = assignment.Id,
|
||||
AssignmentTitle = assignment.Title,
|
||||
Description = assignment.Description,
|
||||
SubjectArea = assignment.Submissions.ToString()
|
||||
});
|
||||
}
|
||||
|
||||
var rootGroups = allGroups.ChildAssignmentGroups.ToList();
|
||||
|
||||
var rootqg = new QuestionGroupDto();
|
||||
|
||||
foreach (var ag in rootGroups.OrderBy(g => g.Number))
|
||||
{
|
||||
var agDto = MapAssignmentGroupToDto(ag);
|
||||
rootqg.SubQuestionGroups.Add(agDto);
|
||||
}
|
||||
|
||||
|
||||
// 递归映射到 ExamDto
|
||||
var examDto = new ExamDto
|
||||
{
|
||||
AssignmentId = assignment.Id,
|
||||
AssignmentTitle = assignment.Title,
|
||||
Description = assignment.Description,
|
||||
SubjectArea = assignment.Submissions.ToString(),
|
||||
QuestionGroups = rootqg
|
||||
};
|
||||
|
||||
return ApiResponse.Success("试卷信息已成功获取。", examDto);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"获取试卷时发生错误: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public QuestionGroupDto MapAssignmentGroupToDto(AssignmentGroup ag)
|
||||
{
|
||||
// 创建当前节点的DTO
|
||||
var dto = new QuestionGroupDto
|
||||
{
|
||||
Title = ag.Title,
|
||||
Score = (int)(ag.TotalPoints ?? 0),
|
||||
Descript = ag.Descript,
|
||||
SubQuestions = ag.AssignmentQuestions?
|
||||
.OrderBy(aq => aq.QuestionNumber)
|
||||
.Select(aq => new SubQuestionDto
|
||||
{
|
||||
Index = aq.QuestionNumber,
|
||||
Stem = aq.Question?.QuestionText,
|
||||
Score = aq.Score ?? 0,
|
||||
SampleAnswer = aq.Question?.CorrectAnswer,
|
||||
QuestionType = aq.Question?.QuestionType.ToString(),
|
||||
DifficultyLevel = aq.Question?.DifficultyLevel.ToString(),
|
||||
Options = new List<OptionDto>() // 根据需要初始化
|
||||
}).ToList() ?? new List<SubQuestionDto>(),
|
||||
SubQuestionGroups = new List<QuestionGroupDto>() // 初始化子集合
|
||||
};
|
||||
|
||||
// 递归处理子组
|
||||
if (ag.ChildAssignmentGroups != null && ag.ChildAssignmentGroups.Count > 0)
|
||||
{
|
||||
foreach (var child in ag.ChildAssignmentGroups.OrderBy(c => c.Number))
|
||||
{
|
||||
var childDto = MapAssignmentGroupToDto(child); // 递归获取子DTO
|
||||
dto.SubQuestionGroups.Add(childDto); // 添加到当前节点的子集合
|
||||
}
|
||||
}
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
private List<QuestionGroupDto> MapAssignmentGroupsToDto2(
|
||||
List<AssignmentGroup> currentLevelGroups,
|
||||
IEnumerable<AssignmentGroup> allFetchedGroups)
|
||||
{
|
||||
var dtos = new List<QuestionGroupDto>();
|
||||
|
||||
foreach (var group in currentLevelGroups.OrderBy(g => g.Number))
|
||||
{
|
||||
var groupDto = new QuestionGroupDto
|
||||
{
|
||||
|
||||
Title = group.Title,
|
||||
Score = (int)(group.TotalPoints ?? 0),
|
||||
Descript = group.Descript,
|
||||
SubQuestions = group.AssignmentQuestions
|
||||
.OrderBy(aq => aq.QuestionNumber)
|
||||
.Select(aq => new SubQuestionDto
|
||||
{
|
||||
Index = aq.QuestionNumber,
|
||||
Stem = aq.Question.QuestionText,
|
||||
Score = aq.Score ?? 0,
|
||||
SampleAnswer = aq.Question.CorrectAnswer,
|
||||
QuestionType = aq.Question.QuestionType.ToString(),
|
||||
DifficultyLevel = aq.Question.DifficultyLevel.ToString(),
|
||||
Options = new List<OptionDto>()
|
||||
}).ToList(),
|
||||
// 递归映射子题组
|
||||
SubQuestionGroups = MapAssignmentGroupsToDto2(
|
||||
allFetchedGroups.Where(ag => ag.ParentGroup == group.Id && !ag.IsDeleted).ToList(),
|
||||
allFetchedGroups)
|
||||
};
|
||||
dtos.Add(groupDto);
|
||||
}
|
||||
return dtos;
|
||||
}
|
||||
|
||||
public async Task<TechHelper.Services.ApiResponse> SaveParsedExam(ExamDto examData)
|
||||
{
|
||||
// 获取当前登录用户
|
||||
var currentUser = await _userManager.FindByEmailAsync(examData.CreaterEmail);
|
||||
if (currentUser == null)
|
||||
{
|
||||
return ApiResponse.Error("未找到当前登录用户,无法保存试题。");
|
||||
}
|
||||
var currentUserId = currentUser.Id;
|
||||
|
||||
try
|
||||
{
|
||||
Guid assignmentId;
|
||||
|
||||
// 创建新的 Assignment 实体
|
||||
var newAssignment = new Assignment
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Title = examData.AssignmentTitle,
|
||||
Description = examData.Description,
|
||||
SubjectArea = examData.SubjectArea,
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
CreatedBy = currentUserId,
|
||||
IsDeleted = false
|
||||
};
|
||||
await _assignmentRepo.InsertAsync(newAssignment);
|
||||
assignmentId = newAssignment.Id;
|
||||
|
||||
|
||||
// 从 ExamDto.QuestionGroups 获取根题组。
|
||||
// 确保只有一个根题组,因为您的模型是“试卷只有一个根节点”。
|
||||
if (examData.QuestionGroups == null)
|
||||
{
|
||||
throw new ArgumentException("试卷必须包含且只能包含一个根题组。");
|
||||
}
|
||||
|
||||
await ProcessAndSaveAssignmentGroupsRecursive(
|
||||
examData.QuestionGroups,
|
||||
examData.SubjectArea.ToString(),
|
||||
assignmentId,
|
||||
null, // 根题组没有父级
|
||||
currentUserId);
|
||||
|
||||
if (await _unitOfWork.SaveChangesAsync() > 0)
|
||||
{
|
||||
return ApiResponse.Success("试卷数据已成功保存。", new ExamDto { AssignmentId = assignmentId, AssignmentTitle = examData.AssignmentTitle });
|
||||
}
|
||||
else
|
||||
{
|
||||
return ApiResponse.Success("没有新的试卷数据需要保存。");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"保存试卷数据失败: {ex.Message}", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessAndSaveAssignmentGroupsRecursive(
|
||||
QuestionGroupDto qgDto,
|
||||
string subjectarea,
|
||||
Guid assignmentId,
|
||||
Guid? parentAssignmentGroupId,
|
||||
Guid createdById)
|
||||
{
|
||||
if (qgDto.ValidQuestionGroup)
|
||||
{
|
||||
await SaveQuestionGroup(qgDto);
|
||||
}
|
||||
else
|
||||
{
|
||||
byte groupNumber = 1;
|
||||
|
||||
|
||||
var newAssignmentGroup = new AssignmentGroup
|
||||
{
|
||||
Id = Guid.NewGuid(), // 后端生成 GUID
|
||||
Title = qgDto.Title,
|
||||
Descript = qgDto.Descript,
|
||||
TotalPoints = qgDto.Score,
|
||||
Number = (byte)qgDto.Index,
|
||||
ValidQuestionGroup = qgDto.ValidQuestionGroup,
|
||||
ParentGroup = parentAssignmentGroupId,
|
||||
AssignmentId = parentAssignmentGroupId == null ? assignmentId : (Guid?)null,
|
||||
IsDeleted = false
|
||||
};
|
||||
await _unitOfWork.GetRepository<AssignmentGroup>().InsertAsync(newAssignmentGroup);
|
||||
|
||||
// 处理子题目
|
||||
uint questionNumber = 1;
|
||||
foreach (var sqDto in qgDto.SubQuestions.OrderBy(s => s.Index))
|
||||
{
|
||||
var newQuestion = _mapper.Map<Question>(sqDto);
|
||||
newQuestion.Id = Guid.NewGuid();
|
||||
newQuestion.CreatedBy = createdById;
|
||||
newQuestion.CreatedAt = DateTime.UtcNow;
|
||||
newQuestion.UpdatedAt = DateTime.UtcNow;
|
||||
newQuestion.IsDeleted = false;
|
||||
newQuestion.SubjectArea = EnumMappingHelpers.ParseEnumSafe(subjectarea, SubjectAreaEnum.Unknown);
|
||||
|
||||
await _unitOfWork.GetRepository<Question>().InsertAsync(newQuestion);
|
||||
|
||||
var newAssignmentQuestion = new AssignmentQuestion
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
QuestionId = newQuestion.Id,
|
||||
QuestionNumber = (byte)questionNumber,
|
||||
AssignmentGroupId = newAssignmentGroup.Id,
|
||||
Score = sqDto.Score,
|
||||
IsDeleted = false,
|
||||
CreatedAt = DateTime.UtcNow
|
||||
};
|
||||
await _unitOfWork.GetRepository<AssignmentQuestion>().InsertAsync(newAssignmentQuestion);
|
||||
|
||||
questionNumber++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// 递归处理子题组
|
||||
// 这里需要遍历 SubQuestionGroups,并对每个子组进行递归调用
|
||||
foreach (var subQgDto in qgDto.SubQuestionGroups.OrderBy(s => s.Index))
|
||||
{
|
||||
await ProcessAndSaveAssignmentGroupsRecursive(
|
||||
subQgDto, // 传入当前的子题组 DTO
|
||||
subjectarea,
|
||||
assignmentId, // 顶层 AssignmentId 依然传递下去,但子组不会直接使用它
|
||||
newAssignmentGroup.Id, // 将当前题组的 ID 作为下一层递归的 parentAssignmentGroupId
|
||||
createdById);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveQuestionGroup(QuestionGroupDto qgDto)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAllExamPreview(Guid user)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assignments = await _unitOfWork.GetRepository<Assignment>().GetAllAsync(
|
||||
predicate: a => a.CreatedBy == user && !a.IsDeleted);
|
||||
|
||||
if (assignments.Any())
|
||||
{
|
||||
var exam = _mapper.Map<IEnumerable<ExamDto>>(assignments);
|
||||
return ApiResponse.Success(result: exam);
|
||||
}
|
||||
|
||||
return ApiResponse.Error("你还没有创建任何试卷");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"查询出了一点问题 , 详细信息为: {ex.Message}, 请稍后再试");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,123 +0,0 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Server.Repository;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
|
||||
public class ExamService2 : IExamService2
|
||||
{
|
||||
private readonly IUnitOfWork _unitOfWork;
|
||||
private readonly IExamRepository _examRepository;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public ExamService2(IUnitOfWork unitOfWork, IExamRepository examRepository, IMapper mapper)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
_examRepository = examRepository;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public async Task<Guid> CreateExamAsync(ExamDto examDto, Guid creatorId)
|
||||
{
|
||||
if (examDto.QuestionGroups == null)
|
||||
{
|
||||
throw new ArgumentException("试卷必须包含一个根题组。");
|
||||
}
|
||||
|
||||
// 使用 AutoMapper 将 DTO 映射到实体
|
||||
var assignment = _mapper.Map<Assignment>(examDto);
|
||||
|
||||
// 设置后端生成的属性
|
||||
assignment.Id = Guid.NewGuid();
|
||||
assignment.CreatedBy = creatorId;
|
||||
assignment.CreatedAt = DateTime.UtcNow;
|
||||
|
||||
// 递归设置所有子实体的ID和关联关系
|
||||
SetEntityIdsAndRelations(assignment.AssignmentGroups.First(), assignment.Id, creatorId);
|
||||
|
||||
await _examRepository.AddAsync(assignment);
|
||||
await _unitOfWork.SaveChangesAsync();
|
||||
|
||||
return assignment.Id;
|
||||
}
|
||||
|
||||
private void SetEntityIdsAndRelations(AssignmentGroup group, Guid? assignmentId, Guid creatorId)
|
||||
{
|
||||
group.Id = Guid.NewGuid();
|
||||
group.AssignmentId = assignmentId;
|
||||
|
||||
foreach (var aq in group.AssignmentQuestions)
|
||||
{
|
||||
aq.Id = Guid.NewGuid();
|
||||
aq.AssignmentGroupId = group.Id;
|
||||
aq.Question.Id = Guid.NewGuid();
|
||||
aq.Question.CreatedBy = creatorId;
|
||||
aq.CreatedAt = DateTime.UtcNow;
|
||||
// ... 其他默认值
|
||||
}
|
||||
|
||||
foreach (var childGroup in group.ChildAssignmentGroups)
|
||||
{
|
||||
// 子题组的 AssignmentId 为 null,通过 ParentGroup 关联
|
||||
SetEntityIdsAndRelations(childGroup, null, creatorId);
|
||||
childGroup.ParentGroup = group.Id;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ExamDto> GetExamByIdAsync(Guid id)
|
||||
{
|
||||
var assignment = await _examRepository.GetFullExamByIdAsync(id);
|
||||
if (assignment == null)
|
||||
{
|
||||
|
||||
throw new InvalidOperationException("");
|
||||
}
|
||||
|
||||
return _mapper.Map<ExamDto>(assignment);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ExamDto>> GetAllExamPreviewsAsync(Guid userId)
|
||||
{
|
||||
var assignments = await _examRepository.GetExamPreviewsByUserAsync(userId);
|
||||
return _mapper.Map<IEnumerable<ExamDto>>(assignments);
|
||||
}
|
||||
|
||||
public async Task AddAsync(QuestionGroupDto qg)
|
||||
{
|
||||
if (qg.ValidQuestionGroup)
|
||||
{
|
||||
var mapQG = _mapper.Map<QuestionGroup>(qg);
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> AddAsync(ExamDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(ExamDto model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -3,7 +3,7 @@ using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IAssignmentGroupService : IBaseService<AssignmentGroup, Guid>
|
||||
public interface IAssignmentGroupService : IBaseService<AssignmentStruct, Guid>
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@@ -4,9 +4,23 @@ using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IExamService : IBaseService<ExamDto, Guid>
|
||||
public interface IExamService : IBaseService<AssignmentDto, Guid>
|
||||
{
|
||||
Task<ApiResponse> GetAllExamPreview(Guid user);
|
||||
QuestionGroupDto MapAssignmentGroupToDto(AssignmentGroup ag);
|
||||
/// <summary>
|
||||
/// 根据 ID 获取试卷 DTO。
|
||||
/// </summary>
|
||||
Task<AssignmentDto> GetExamByIdAsync(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户的所有试卷预览。
|
||||
/// </summary>
|
||||
Task<ApiResponse> GetAllExamPreviewsAsync(Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的试卷。
|
||||
/// </summary>
|
||||
/// <returns>创建成功的试卷ID</returns>
|
||||
Task<ApiResponse> CreateExamAsync(AssignmentDto examDto);
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -1,26 +0,0 @@
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IExamService2 : IBaseService<ExamDto, Guid>
|
||||
{
|
||||
/// <summary>
|
||||
/// 根据 ID 获取试卷 DTO。
|
||||
/// </summary>
|
||||
Task<ExamDto> GetExamByIdAsync(Guid id);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户的所有试卷预览。
|
||||
/// </summary>
|
||||
Task<IEnumerable<ExamDto>> GetAllExamPreviewsAsync(Guid userId);
|
||||
|
||||
/// <summary>
|
||||
/// 创建一个新的试卷。
|
||||
/// </summary>
|
||||
/// <returns>创建成功的试卷ID</returns>
|
||||
Task<Guid> CreateExamAsync(ExamDto examDto, Guid creatorId);
|
||||
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
using Entities.Contracts;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public interface IQuestionGroupService : IBaseService<QuestionGroup, Guid>
|
||||
{
|
||||
}
|
||||
}
|
@@ -1,66 +0,0 @@
|
||||
using AutoMapper;
|
||||
using Entities.Contracts;
|
||||
using Entities.DTO;
|
||||
using SharedDATA.Api;
|
||||
using TechHelper.Services;
|
||||
|
||||
namespace TechHelper.Server.Services
|
||||
{
|
||||
public class QuestionGroupService : IAssignmentGroupService
|
||||
{
|
||||
|
||||
private readonly IUnitOfWork _work;
|
||||
// 如果不再需要 AutoMapper 进行实体到 DTO 的映射,可以移除 _mapper 字段
|
||||
// 但如果 AutoMapper 在其他服务中用于其他映射,或者将来可能需要,可以保留
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IExamService _examService;
|
||||
|
||||
public QuestionGroupService(IUnitOfWork work, IMapper mapper, IExamService examService)
|
||||
{
|
||||
_work = work;
|
||||
_mapper = mapper;
|
||||
_examService = examService;
|
||||
}
|
||||
|
||||
|
||||
public Task<ApiResponse> AddAsync(AssignmentGroup model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> DeleteAsync(Guid id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<ApiResponse> GetAllAsync(QueryParameter query)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<ApiResponse> GetAsync(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
var result = await _work.GetRepository<AssignmentGroup>().GetFirstOrDefaultAsync(predicate: ag => ag.Id == id);
|
||||
QuestionGroupDto qgd = new QuestionGroupDto();
|
||||
if (result != null)
|
||||
{
|
||||
qgd = _examService.MapAssignmentGroupToDto(result);
|
||||
return ApiResponse.Success(result: qgd);
|
||||
}
|
||||
return ApiResponse.Error("没找到问题组");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return ApiResponse.Error($"出现了一点问题: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ApiResponse> UpdateAsync(AssignmentGroup model)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
@@ -31,12 +31,12 @@ namespace TechHelper.Server.Services
|
||||
{
|
||||
// 可以在此处进行业务逻辑校验,例如检查题目是否已存在
|
||||
var existingQuestion = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.QuestionText == model.QuestionText && !q.IsDeleted
|
||||
predicate: q => q.Title == model.Title && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (existingQuestion != null)
|
||||
{
|
||||
return ApiResponse.Error($"题目 '{model.QuestionText}' 已存在,请勿重复添加。");
|
||||
return ApiResponse.Error($"题目 '{model.Title}' 已存在,请勿重复添加。");
|
||||
}
|
||||
|
||||
// 设置创建时间、创建者等通用属性
|
||||
@@ -44,8 +44,7 @@ namespace TechHelper.Server.Services
|
||||
model.CreatedAt = DateTime.UtcNow;
|
||||
model.UpdatedAt = DateTime.UtcNow;
|
||||
model.IsDeleted = false;
|
||||
model.ValidQuestion = true; // 假设新添加的题目默认为有效
|
||||
// model.CreatedBy = ... // 实际应用中,这里应该从当前用户上下文获取
|
||||
|
||||
|
||||
await _work.GetRepository<Question>().InsertAsync(model);
|
||||
await _work.SaveChangesAsync();
|
||||
@@ -90,7 +89,7 @@ namespace TechHelper.Server.Services
|
||||
try
|
||||
{
|
||||
var question = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.QuestionText == title && !q.IsDeleted
|
||||
predicate: q => q.Title == title && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (question == null)
|
||||
@@ -119,10 +118,10 @@ namespace TechHelper.Server.Services
|
||||
var distinctTitles = titles.Distinct(StringComparer.OrdinalIgnoreCase).ToList();
|
||||
|
||||
var existingQuestions = await _work.GetRepository<Question>().GetAllAsync(
|
||||
predicate: q => distinctTitles.Contains(q.QuestionText) && !q.IsDeleted
|
||||
predicate: q => distinctTitles.Contains(q.Title) && !q.IsDeleted
|
||||
);
|
||||
|
||||
var existingQuestionTexts = new HashSet<string>(existingQuestions.Select(q => q.QuestionText), StringComparer.OrdinalIgnoreCase);
|
||||
var existingQuestionTexts = new HashSet<string>(existingQuestions.Select(q => q.Title), StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
var resultDictionary = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
|
||||
foreach (var title in titles)
|
||||
@@ -146,7 +145,7 @@ namespace TechHelper.Server.Services
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(query.Search))
|
||||
{
|
||||
predicate = predicate.And(q => q.QuestionText.Contains(query.Search));
|
||||
predicate = predicate.And(q => q.Title.Contains(query.Search));
|
||||
}
|
||||
|
||||
Func<IQueryable<Question>, IOrderedQueryable<Question>> orderBy = null;
|
||||
@@ -214,12 +213,12 @@ namespace TechHelper.Server.Services
|
||||
|
||||
// 检查更新后的题目文本是否与现有其他题目重复
|
||||
var duplicateCheck = await _work.GetRepository<Question>().GetFirstOrDefaultAsync(
|
||||
predicate: q => q.Id != model.Id && q.QuestionText == model.QuestionText && !q.IsDeleted
|
||||
predicate: q => q.Id != model.Id && q.Title == model.Title && !q.IsDeleted
|
||||
);
|
||||
|
||||
if (duplicateCheck != null)
|
||||
{
|
||||
return ApiResponse.Error($"题目文本 '{model.QuestionText}' 已被其他题目占用,请修改。");
|
||||
return ApiResponse.Error($"题目文本 '{model.Title}' 已被其他题目占用,请修改。");
|
||||
}
|
||||
|
||||
// 手动复制属性或使用 AutoMapper (如果保留了 _mapper 字段)
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
|
@@ -6,7 +6,7 @@
|
||||
}
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"XSDB": "Server=mysql.eazygame.cn;Port=13002;Database=test;User=root;Password=wx1998WX"
|
||||
"XSDB": "Server=mysql.eazygame.cn;Port=13002;Database=test1;User=root;Password=wx1998WX"
|
||||
},
|
||||
"JWTSettings": {
|
||||
"securityKey": "MxcxQHVYVDQ0U3lqWkIwdjZlSGx4eFp6YnFpUGxodmc5Y3hPZk5vWm9MZEg2Y0I=",
|
||||
|
Reference in New Issue
Block a user