添加项目文件。
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentAttachmentConfiguration : IEntityTypeConfiguration<AssignmentAttachment>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<AssignmentAttachment> builder)
|
||||
{
|
||||
builder.ToTable("assignment_attachments");
|
||||
|
||||
builder.HasKey(aa => aa.Id);
|
||||
|
||||
builder.Property(aa => aa.Id)
|
||||
.HasColumnName("id");
|
||||
|
||||
builder.Property(aa => aa.AssignmentId)
|
||||
.HasColumnName("assignment_id")
|
||||
.IsRequired();
|
||||
|
||||
builder.Property(aa => aa.FilePath)
|
||||
.HasColumnName("file_path")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255);
|
||||
|
||||
builder.Property(aa => aa.FileName)
|
||||
.HasColumnName("file_name")
|
||||
.IsRequired()
|
||||
.HasMaxLength(255);
|
||||
|
||||
builder.Property(aa => aa.UploadedAt)
|
||||
.HasColumnName("uploaded_at")
|
||||
.ValueGeneratedOnAdd(); // Set value on creation
|
||||
|
||||
builder.Property(aa => aa.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
// Configure the relationship explicitly
|
||||
builder.HasOne(aa => aa.Assignment) // An AssignmentAttachment has one Assignment
|
||||
.WithMany(a => a.AssignmentAttachments) // An Assignment has many AssignmentAttachments (assuming 'Attachments' collection in Assignment)
|
||||
.HasForeignKey(aa => aa.AssignmentId) // The foreign key is AssignmentAttachment.AssignmentId
|
||||
.IsRequired() // It's a required relationship based on your [Required] attribute
|
||||
.OnDelete(DeleteBehavior.Cascade); // If an Assignment is deleted, its attachments should also be deleted
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentClassConfiguration : IEntityTypeConfiguration<AssignmentClass>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<AssignmentClass> builder)
|
||||
{
|
||||
// 设置表名为 "assignment_class"
|
||||
builder.ToTable("assignment_class");
|
||||
|
||||
// 设置复合主键
|
||||
builder.HasKey(ac => new { ac.AssignmentId, ac.ClassId });
|
||||
|
||||
// 配置 AssignmentId 列名
|
||||
builder.Property(ac => ac.AssignmentId)
|
||||
.HasColumnName("assignment_id");
|
||||
|
||||
// 配置 ClassId 列名
|
||||
builder.Property(ac => ac.ClassId)
|
||||
.HasColumnName("class_id");
|
||||
|
||||
// 配置 AssignedAt 列名
|
||||
builder.Property(ac => ac.AssignedAt)
|
||||
.HasColumnName("assigned_at")
|
||||
.IsRequired(); // 通常时间字段不能为空
|
||||
|
||||
// 配置 IsDeleted 列名
|
||||
builder.Property(ac => ac.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 可以设置默认值,表示默认未删除
|
||||
|
||||
// 配置到 Assignment 的关系 (多对一)
|
||||
// 假设 Assignment 类中有一个名为 AssignmentClasses 的集合属性
|
||||
builder.HasOne(ac => ac.Assignment) // AssignmentClass 有一个 Assignment
|
||||
.WithMany(a => a.AssignmentClasses) // Assignment 有多个 AssignmentClass 记录
|
||||
.HasForeignKey(ac => ac.AssignmentId) // 通过 AssignmentId 建立外键
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Assignment 被删除时,相关的 AssignmentClass 记录也级联删除
|
||||
|
||||
// 配置到 Class 的关系 (多对一)
|
||||
// 假设 Class 类中有一个名为 AssignmentClasses 的集合属性
|
||||
builder.HasOne(ac => ac.Class) // AssignmentClass 有一个 Class
|
||||
.WithMany(c => c.AssignmentClasses) // Class 有多个 AssignmentClass 记录
|
||||
.HasForeignKey(ac => ac.ClassId) // 通过 ClassId 建立外键
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 AssignmentClass 记录也级联删除
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentConfiguration : IEntityTypeConfiguration<Assignment>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Assignment> builder)
|
||||
{
|
||||
builder.ToTable("assignments");
|
||||
|
||||
builder.HasKey(a => a.Id);
|
||||
|
||||
builder.Property(a => a.Id)
|
||||
.HasColumnName("id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
builder.Property(a => a.Title)
|
||||
.IsRequired()
|
||||
.HasColumnName("title")
|
||||
.HasMaxLength(255);
|
||||
|
||||
builder.Property(a => a.Description)
|
||||
.HasColumnName("description");
|
||||
|
||||
builder.Property(a => a.DueDate)
|
||||
.IsRequired()
|
||||
.HasColumnName("due_date");
|
||||
|
||||
builder.Property(a => a.TotalPoints)
|
||||
.HasColumnName("total_points");
|
||||
|
||||
builder.Property(a => a.CreatedBy)
|
||||
.HasColumnName("created_by");
|
||||
|
||||
builder.Property(a => a.CreatedAt)
|
||||
.IsRequired()
|
||||
.HasColumnName("created_at");
|
||||
|
||||
builder.Property(a => a.UpdatedAt)
|
||||
.IsRequired()
|
||||
.HasColumnName("updated_at");
|
||||
|
||||
builder.Property(a => a.IsDeleted)
|
||||
.HasColumnName("deleted");
|
||||
|
||||
// 配置导航属性和关系
|
||||
|
||||
// 关系: Assignment (多) 到 User (一) - CreatedBy 外键
|
||||
// 假设 User 实体有 Id 作为主键
|
||||
// .WithMany() 表示 User 有多个 Assignment,但这里不指定 User 上的导航属性名称
|
||||
// 如果 User 有一个名为 AssignmentsCreated 的导航属性,应写为 .WithMany(u => u.AssignmentsCreated)
|
||||
builder.HasOne(a => a.Creator)
|
||||
.WithMany() // User 实体没有指向 Assignment 的导航属性 (或我们不知道)
|
||||
.HasForeignKey(a => a.CreatedBy)
|
||||
.IsRequired(); // CreatedBy 是必填的,对应 [Required] 在外键属性上
|
||||
|
||||
// 关系: Assignment (一) 到 AssignmentClass (多)
|
||||
// 假设 AssignmentClass 实体包含一个名为 AssignmentId 的外键属性
|
||||
builder.HasMany(a => a.AssignmentClasses)
|
||||
.WithOne(ac => ac.Assignment) // AssignmentClass 没有指向 Assignment 的导航属性 (或我们不知道)
|
||||
.HasForeignKey("AssignmentId") // 指定外键名称为 AssignmentId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 如果 Assignment 被删除,关联的 AssignmentClass 也会被删除
|
||||
|
||||
// 关系: Assignment (一) 到 AssignmentAttachment (多)
|
||||
// 假设 AssignmentAttachment 实体包含一个名为 AssignmentId 的外键属性
|
||||
builder.HasMany(a => a.AssignmentAttachments)
|
||||
.WithOne(aa => aa.Assignment)
|
||||
.HasForeignKey("AssignmentId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
// 关系: Assignment (一) 到 Submission (多)
|
||||
// 假设 Submission 实体包含一个名为 AssignmentId 的外键属性
|
||||
builder.HasMany(a => a.Submissions)
|
||||
.WithOne(s => s.Assignment)
|
||||
.HasForeignKey("AssignmentId")
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentGroupConfiguration : IEntityTypeConfiguration<AssignmentGroup>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<AssignmentGroup> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
// 将此实体映射到数据库中名为 "assignment_detail" 的表。
|
||||
builder.ToTable("assignment_group");
|
||||
|
||||
// 2. 配置主键
|
||||
// Id 属性作为主键。
|
||||
builder.HasKey(ag => ag.Id);
|
||||
|
||||
// 3. 配置列名、必需性、长度和默认值
|
||||
|
||||
// 配置 Id 属性对应的数据库列名为 "id"。
|
||||
builder.Property(ag => ag.Id)
|
||||
.HasColumnName("id");
|
||||
// EF Core 默认 Guid 类型主键由应用程序生成,因此无需 ValueGeneratedOnAdd()。
|
||||
|
||||
// 配置 AssignmentId 属性对应的数据库列名为 "assignment",并设置为必需字段。
|
||||
builder.Property(ag => ag.AssignmentId)
|
||||
.HasColumnName("assignment")
|
||||
.IsRequired();
|
||||
|
||||
// 配置 Title 属性对应的数据库列名为 "title",设置为必需字段,并设置最大长度。
|
||||
builder.Property(ag => ag.Title)
|
||||
.HasColumnName("title")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// 配置 Descript 属性对应的数据库列名为 "descript",并设置最大长度。
|
||||
builder.Property(ag => ag.Descript)
|
||||
.HasColumnName("descript")
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// 配置 TotalPoints 属性对应的数据库列名为 "total_points"。
|
||||
// TotalPoints 是 decimal? 类型,默认就是可选的,无需 IsRequired(false)。
|
||||
builder.Property(ag => ag.TotalPoints)
|
||||
.HasColumnName("total_points");
|
||||
|
||||
// 配置 Number 属性对应的数据库列名为 "number"。
|
||||
builder.Property(ag => ag.Number)
|
||||
.HasColumnName("number")
|
||||
.IsRequired(); // byte 默认非空,显式 IsRequired 增加可读性。
|
||||
|
||||
// 配置 ParentGroup 属性对应的数据库列名为 "sub_group"。
|
||||
// ParentGroup 是 Guid? 类型,默认就是可选的,无需 IsRequired(false)。
|
||||
builder.Property(ag => ag.ParentGroup)
|
||||
.HasColumnName("sub_group");
|
||||
|
||||
// 配置 IsDeleted 属性对应的数据库列名为 "deleted",并设置默认值为 false。
|
||||
builder.Property(ag => ag.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 适用于软删除策略
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// 配置 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 记录也级联删除。
|
||||
|
||||
// 配置 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 建立外键
|
||||
.IsRequired(false) // SubGroup 是可空的 (Guid?),所以这个关系是可选的。
|
||||
.OnDelete(DeleteBehavior.SetNull); // 当父 AssignmentGroup 被删除时,其子 AssignmentGroup 的 SubGroup 外键将被设置为 NULL。
|
||||
// 如果你希望父组被删除时子组不能脱离父组(即不允许父组被删除),
|
||||
// 可以使用 DeleteBehavior.Restrict 或 DeleteBehavior.NoAction。
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,86 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class AssignmentQuestionConfiguration : IEntityTypeConfiguration<AssignmentQuestion>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<AssignmentQuestion> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
builder.ToTable("assignment_questions");
|
||||
|
||||
// 2. 设置主键
|
||||
builder.HasKey(aq => aq.Id);
|
||||
|
||||
// 3. 配置列名、必需性及其他属性
|
||||
|
||||
// 配置 Id 列
|
||||
builder.Property(aq => aq.Id)
|
||||
.HasColumnName("id");
|
||||
|
||||
// 配置 QuestionId 列 (已修正拼写)
|
||||
builder.Property(aq => aq.QuestionId)
|
||||
.HasColumnName("question_id")
|
||||
.IsRequired();
|
||||
|
||||
// 配置 QuestionNumber 列
|
||||
builder.Property(aq => aq.QuestionNumber)
|
||||
.HasColumnName("question_number")
|
||||
.IsRequired(); // uint 类型默认非空
|
||||
|
||||
// 配置 CreatedAt 列
|
||||
builder.Property(aq => aq.CreatedAt)
|
||||
.HasColumnName("created_at")
|
||||
.IsRequired(); // 通常创建时间字段是非空的
|
||||
|
||||
// 配置 AssignmentGroupId 列
|
||||
// 该列在数据库中名为 "detail_id"
|
||||
builder.Property(aq => aq.AssignmentGroupId)
|
||||
.HasColumnName("detail_id")
|
||||
.IsRequired();
|
||||
|
||||
// 配置 IsDeleted 列
|
||||
builder.Property(aq => aq.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 适用于软删除策略
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 AssignmentQuestion 到 Question 的关系 (多对一)
|
||||
// 一个 AssignmentQuestion 属于一个 Question。
|
||||
//
|
||||
// 假设 `Question` 实体中有一个名为 `AssignmentQuestions` 的 `ICollection<AssignmentQuestion>` 集合属性。
|
||||
builder.HasOne(aq => aq.Question) // 当前 AssignmentQuestion 有一个 Question
|
||||
.WithMany(q => q.AssignmentQuestions) // 那个 Question 可以有多个 AssignmentQuestion
|
||||
.HasForeignKey(aq => aq.QuestionId) // 外键是 AssignmentQuestion.QuestionId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Question 被删除时,相关的 AssignmentQuestion 也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 AssignmentQuestion 到 AssignmentGroup 的关系 (多对一)
|
||||
// 一个 AssignmentQuestion 属于一个 AssignmentGroup。
|
||||
//
|
||||
// 你的 `AssignmentQuestion` 类现在有了 `public AssignmentGroup AssignmentGroup { get; set; }`
|
||||
// 这是一个非常好的改进,它与 `AssignmentGroupId` 外键完美匹配。
|
||||
// 假设 `AssignmentGroup` 实体中有一个名为 `AssignmentQuestions` 的 `ICollection<AssignmentQuestion>` 集合属性。
|
||||
builder.HasOne(aq => aq.AssignmentGroup) // 当前 AssignmentQuestion 有一个 AssignmentGroup
|
||||
.WithMany(ag => ag.AssignmentQuestions) // 那个 AssignmentGroup 可以有多个 AssignmentQuestion
|
||||
.HasForeignKey(aq => aq.AssignmentGroupId) // 外键是 AssignmentQuestion.AssignmentGroupId (列名 detail_id)
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 AssignmentGroup 被删除时,相关的 AssignmentQuestion 也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 AssignmentQuestion 到 SubmissionDetail 的关系 (一对多)
|
||||
// 一个 AssignmentQuestion 可以有多个 SubmissionDetail。
|
||||
//
|
||||
// 这个关系通常从 "多" 的一方(`SubmissionDetail` 实体)来配置外键。
|
||||
// 假设 `SubmissionDetail` 实体有一个 `AssignmentQuestionId` 外键和 `AssignmentQuestion` 导航属性。
|
||||
builder.HasMany(aq => aq.SubmissionDetails) // 当前 AssignmentQuestion 有多个 SubmissionDetail
|
||||
.WithOne(sd => sd.AssignmentQuestion); // 每一个 SubmissionDetail 都有一个 AssignmentQuestion
|
||||
// .HasForeignKey(sd => sd.AssignmentQuestionId); // 外键的配置应在 `SubmissionDetailConfiguration` 中进行
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class ClassConfiguration : IEntityTypeConfiguration<Class>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Class> builder)
|
||||
{
|
||||
// 1. 表名映射
|
||||
builder.ToTable("classes");
|
||||
|
||||
// 2. 主键
|
||||
builder.HasKey(c => c.Id);
|
||||
builder.Property(c => c.Id)
|
||||
.HasColumnName("id");
|
||||
|
||||
builder.Property(c => c.Grade)
|
||||
.HasColumnName("grade");
|
||||
|
||||
// 3. Name 属性
|
||||
builder.Property(c => c.Number)
|
||||
.HasColumnName("class");
|
||||
|
||||
// 4. Description 属性
|
||||
builder.Property(c => c.Description)
|
||||
.HasColumnName("description")
|
||||
.IsRequired(false); // 明确其为可选,尽管 string 类型默认是可空的。
|
||||
|
||||
// 5. TeacherId (外键)
|
||||
builder.Property(c => c.HeadTeacherId)
|
||||
.HasColumnName("head_teacher_id")
|
||||
.IsRequired(false);
|
||||
|
||||
// 6. CreatedAt 属性
|
||||
builder.Property(c => c.CreatedAt)
|
||||
.HasColumnName("created_at")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAdd();
|
||||
// DateTime 是非可空类型,因此按类型是必需的。
|
||||
// 如果希望数据库在创建时设置默认值,可以考虑 .HasDefaultValueSql("GETUTCDATE()") (SQL Server) 或类似方法。
|
||||
|
||||
// 7. UpdatedAt 属性
|
||||
builder.Property(c => c.UpdatedAt)
|
||||
.HasColumnName("updated_at")
|
||||
.IsRequired()
|
||||
.ValueGeneratedOnAddOrUpdate(); // DateTime 是非可空类型。
|
||||
// 如果需要在修改时自动更新,可以考虑配置(例如通过拦截器或触发器)。
|
||||
|
||||
// 8. IsDeleted 属性 (用于软删除)
|
||||
builder.Property(c => c.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.IsRequired()
|
||||
.HasDefaultValue(false); // 通常默认为未删除。
|
||||
|
||||
// --- 导航属性配置 ---
|
||||
|
||||
// 9. 与 User (Teacher) 的关系
|
||||
builder.Property(c => c.HeadTeacherId).HasColumnName("head_teacher_id");
|
||||
builder.HasOne(c => c.HeadTeacher) // Class 实体中的导航属性
|
||||
.WithMany() // User 实体中可以不定义反向导航到其作为班主任的班级集合
|
||||
// 如果 User 实体中有 public ICollection<Class> HeadManagedClasses { get; set; }
|
||||
// 则这里应为 .WithMany(u => u.HeadManagedClasses)
|
||||
.HasForeignKey(c => c.HeadTeacherId) // Class 实体中的外键
|
||||
.IsRequired() // 班主任是必需的
|
||||
.OnDelete(DeleteBehavior.Restrict); // 删除用户时,如果其是班主任,则限制删除
|
||||
|
||||
// --- 授课老师关系 (多对多) ---
|
||||
// 这个关系主要通过 ClassTeacherConfiguration 来定义其两端。
|
||||
// Class 到 ClassTeacher 是一对多。
|
||||
builder.HasMany(c => c.ClassTeachers) // Class 实体中的集合导航属性
|
||||
.WithOne(ct => ct.Class) // ClassTeacher 实体中指向 Class 的导航属性
|
||||
.HasForeignKey(ct => ct.ClassId) // ClassTeacher 实体中的外键
|
||||
.OnDelete(DeleteBehavior.Cascade); // 如果班级被删除,相关的教师关联也应删除
|
||||
|
||||
// 10. 与 ClassStudent 的关系 (多对多中间表或一对多)
|
||||
// 一对多:一个 Class 有多个 ClassStudent。一个 ClassStudent 属于一个 Class。
|
||||
// 假设 ClassStudent 有 'ClassId' 外键和 'Class' 导航属性。
|
||||
builder.HasMany(c => c.ClassStudents) // Class 中的集合导航属性
|
||||
.WithOne(cs => cs.Class) // 假设 ClassStudent 中有 'public Class Class { get; set; }'
|
||||
.HasForeignKey(cs => cs.ClassId) // 假设 ClassStudent 中有 'public Guid ClassId { get; set; }'
|
||||
.OnDelete(DeleteBehavior.Cascade); // 常见:如果一个班级被删除,其学生注册记录也应被删除。
|
||||
|
||||
// 11. 与 AssignmentClass 的关系 (多对多中间表或一对多)
|
||||
// 一对多:一个 Class 有多个 AssignmentClass。一个 AssignmentClass 属于一个 Class。
|
||||
// 假设 AssignmentClass 有 'ClassId' 外键和 'Class' 导航属性。
|
||||
builder.HasMany(c => c.AssignmentClasses) // Class 中的集合导航属性
|
||||
.WithOne(ac => ac.Class) // 假设 AssignmentClass 中有 'public Class Class { get; set; }'
|
||||
.HasForeignKey(ac => ac.ClassId) // 假设 AssignmentClass 中有 'public Guid ClassId { get; set; }'
|
||||
.OnDelete(DeleteBehavior.Cascade); // 常见:如果一个班级被删除,其作业关联也应被删除。
|
||||
|
||||
// --- 可选:索引 ---
|
||||
// builder.HasIndex(c => c.TeacherId).HasDatabaseName("IX_classes_teacher_id");
|
||||
// builder.HasIndex(c => c.Name).IsUnique(false).HasDatabaseName("IX_classes_name"); // 如果经常按名称搜索
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class ClassStudentConfiguration : IEntityTypeConfiguration<ClassStudent>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ClassStudent> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
// 将此实体映射到数据库中名为 "class_student" 的表。
|
||||
builder.ToTable("class_student");
|
||||
|
||||
// 2. 设置复合主键
|
||||
// ClassId 和 StudentId 的组合作为主键,确保一个班级中一个学生只有一条入学记录。
|
||||
builder.HasKey(cs => new { cs.ClassId, cs.StudentId });
|
||||
|
||||
// 3. 配置列名和属性特性
|
||||
|
||||
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
|
||||
builder.Property(cs => cs.ClassId)
|
||||
.HasColumnName("class_id");
|
||||
|
||||
// 配置 StudentId 属性对应的数据库列名为 "student_id"。
|
||||
builder.Property(cs => cs.StudentId)
|
||||
.HasColumnName("student_id");
|
||||
|
||||
// 配置 EnrollmentDate 属性对应的数据库列名为 "enrollment_date",并设置为必需字段。
|
||||
builder.Property(cs => cs.EnrollmentDate)
|
||||
.HasColumnName("enrollment_date")
|
||||
.IsRequired();
|
||||
|
||||
// 配置 IsDeleted 属性对应的数据库列名为 "deleted",并设置默认值为 false。
|
||||
builder.Property(cs => cs.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 常用作软删除标记
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 ClassStudent 到 Class 的关系 (多对一)
|
||||
// 一个 ClassStudent 联结记录属于一个 Class。
|
||||
//
|
||||
// 假设 `Class` 实体中有一个名为 `ClassStudents` 的 `ICollection<ClassStudent>` 集合属性。
|
||||
builder.HasOne(cs => cs.Class) // 当前 ClassStudent 链接到一个 Class
|
||||
.WithMany(c => c.ClassStudents) // 那个 Class 可以有多个 ClassStudent 记录
|
||||
.HasForeignKey(cs => cs.ClassId) // 外键是 ClassStudent.ClassId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassStudent 记录也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 ClassStudent 到 User (Student) 的关系 (多对一)
|
||||
// 一个 ClassStudent 联结记录属于一个 User (作为 Student)。
|
||||
//
|
||||
// 假设 `User` 实体中有一个名为 `EnrolledClassesLink` 的 `ICollection<ClassStudent>` 集合属性,
|
||||
// 用于表示该用户所注册的班级联结记录 (与 `ClassTeacherConfiguration` 中的模式类似)。
|
||||
builder.HasOne(cs => cs.Student) // 当前 ClassStudent 链接到一个 User (学生)
|
||||
.WithMany(u => u.EnrolledClassesLink) // 那个 User (学生) 可以有多个 ClassStudent 记录
|
||||
.HasForeignKey(cs => cs.StudentId) // 外键是 ClassStudent.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (学生) 被删除时,如果还有相关的 ClassStudent 记录,则会阻止删除。
|
||||
// 这是更安全的做法,以避免意外数据丢失。如果你希望学生被删除时,其所有注册关系也一并删除,可改为 DeleteBehavior.Cascade。
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,61 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class ClassTeacherConfiguration : IEntityTypeConfiguration<ClassTeacher>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<ClassTeacher> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
// 将此实体映射到数据库中名为 "class_teachers" 的表。
|
||||
builder.ToTable("class_teachers");
|
||||
|
||||
// 2. 设置复合主键
|
||||
// ClassId 和 TeacherId 的组合作为主键,确保一个班级中一个老师只有一条任教记录。
|
||||
// 这要求 ClassTeacher 类中的 ClassId 和 TeacherId 属性上都添加了 [Key] 特性。
|
||||
builder.HasKey(ct => new { ct.ClassId, ct.TeacherId });
|
||||
|
||||
// 3. 配置列名和属性特性
|
||||
|
||||
// 配置 ClassId 属性对应的数据库列名为 "class_id"。
|
||||
builder.Property(ct => ct.ClassId)
|
||||
.HasColumnName("class_id");
|
||||
|
||||
// 配置 TeacherId 属性对应的数据库列名为 "teacher_id"。
|
||||
builder.Property(ct => ct.TeacherId)
|
||||
.HasColumnName("teacher_id");
|
||||
|
||||
// 配置 SubjectTaught 属性对应的数据库列名为 "subject_taught"。
|
||||
// 假设 SubjectTaught 可以为空,所以没有 .IsRequired()
|
||||
builder.Property(ct => ct.SubjectTaught)
|
||||
.HasColumnName("subject_taught");
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 ClassTeacher 到 Class 的关系 (多对一)
|
||||
// 一个 ClassTeacher 联结记录属于一个 Class。
|
||||
//
|
||||
// 假设 `Class` 实体中有一个名为 `ClassTeachers` 的 `ICollection<ClassTeacher>` 集合属性。
|
||||
builder.HasOne(ct => ct.Class) // 当前 ClassTeacher 链接到一个 Class
|
||||
.WithMany(c => c.ClassTeachers) // 那个 Class 可以有多个 ClassTeacher 记录
|
||||
.HasForeignKey(ct => ct.ClassId) // 外键是 ClassTeacher.ClassId
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 Class 被删除时,相关的 ClassTeacher 记录也级联删除。
|
||||
|
||||
// ---
|
||||
// 配置 ClassTeacher 到 User (Teacher) 的关系 (多对一)
|
||||
// 一个 ClassTeacher 联结记录属于一个 User (作为 Teacher)。
|
||||
//
|
||||
// 假设 `User` 实体中有一个名为 `TaughtClassesLink` 的 `ICollection<ClassTeacher>` 集合属性,
|
||||
// 用于表示该用户所教授的班级联结记录。
|
||||
builder.HasOne(ct => ct.Teacher) // 当前 ClassTeacher 链接到一个 User (老师)
|
||||
.WithMany(u => u.TaughtClassesLink) // 那个 User (老师) 可以有多个 ClassTeacher 记录 (为所教授的班级)
|
||||
.HasForeignKey(ct => ct.TeacherId) // 外键是 ClassTeacher.TeacherId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (老师) 被删除时,如果还有相关的 ClassTeacher 记录,则会阻止删除。
|
||||
// 这通常是防止数据丢失的更安全选择。如果你希望老师被删除时,其所有任教关系也一并删除,可改为 DeleteBehavior.Cascade。
|
||||
}
|
||||
}
|
||||
|
||||
}
|
102
TechHelper.Server/Context/Configuration/QuestionConfiguration.cs
Normal file
102
TechHelper.Server/Context/Configuration/QuestionConfiguration.cs
Normal file
@@ -0,0 +1,102 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class QuestionConfiguration : IEntityTypeConfiguration<Question>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Question> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
builder.ToTable("questions");
|
||||
|
||||
// 2. 设置主键
|
||||
builder.HasKey(q => q.Id);
|
||||
|
||||
// 3. 配置列名、必需性、长度及其他属性
|
||||
|
||||
// Id
|
||||
builder.Property(q => q.Id)
|
||||
.HasColumnName("id");
|
||||
// 对于 Guid 类型的主键,EF Core 默认由应用程序生成值,无需 ValueGeneratedOnAdd()
|
||||
|
||||
// QuestionText
|
||||
builder.Property(q => q.QuestionText)
|
||||
.HasColumnName("question_text")
|
||||
.IsRequired()
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// QuestionType (枚举作为字符串存储)
|
||||
builder.Property(q => q.QuestionType)
|
||||
.HasColumnName("question_type")
|
||||
.IsRequired()
|
||||
.HasConversion<string>() // <-- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(20); // <-- 应用最大长度
|
||||
|
||||
// CorrectAnswer
|
||||
builder.Property(q => q.CorrectAnswer)
|
||||
.HasColumnName("correct_answer")
|
||||
.HasMaxLength(65535); // 对应 MaxLength(65535)
|
||||
|
||||
// DifficultyLevel (枚举作为字符串存储)
|
||||
builder.Property(q => q.DifficultyLevel)
|
||||
.HasColumnName("difficulty_level")
|
||||
.HasConversion<string>() // <-- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(10); // <-- 应用最大长度
|
||||
// DifficultyLevel 属性没有 [Required],所以默认是可选的
|
||||
|
||||
// SubjectArea
|
||||
builder.Property(q => q.SubjectArea)
|
||||
.HasColumnName("subject_area")
|
||||
.HasConversion<string>() // <--- 重要:将枚举存储为字符串
|
||||
.HasMaxLength(100); // <--- 应用最大长度 (从原 StringLength 继承)
|
||||
|
||||
// CreatedBy
|
||||
builder.Property(q => q.CreatedBy)
|
||||
.HasColumnName("created_by")
|
||||
.IsRequired();
|
||||
|
||||
// CreatedAt (自动在添加时设置)
|
||||
builder.Property(q => q.CreatedAt)
|
||||
.HasColumnName("created_at")
|
||||
.IsRequired() // 通常创建时间是必需的
|
||||
.ValueGeneratedOnAdd(); // EF Core 在实体添加时自动设置值
|
||||
|
||||
// UpdatedAt (自动在添加或更新时设置,并作为并发令牌)
|
||||
builder.Property(q => q.UpdatedAt)
|
||||
.HasColumnName("updated_at")
|
||||
.IsRequired() // 通常更新时间是必需的
|
||||
.ValueGeneratedOnAddOrUpdate() // EF Core 在实体添加或更新时自动设置值
|
||||
.IsConcurrencyToken(); // 用作乐观并发令牌,防止数据冲突
|
||||
|
||||
// IsDeleted (软删除标记,默认 false)
|
||||
builder.Property(q => q.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false);
|
||||
|
||||
// 4. 配置导航属性和外键关系
|
||||
|
||||
// ---
|
||||
// 配置 Question 到 User (Creator) 的关系 (多对一)
|
||||
// 一个 Question 由一个 User (Creator) 创建。
|
||||
//
|
||||
// 假设 `User` 实体中有一个名为 `CreatedQuestions` 的 `ICollection<Question>` 集合属性。
|
||||
builder.HasOne(q => q.Creator) // 当前 Question 有一个 Creator
|
||||
.WithMany(u => u.CreatedQuestions) // 那个 Creator 可以创建多个 Question
|
||||
.HasForeignKey(q => q.CreatedBy) // 外键是 Question.CreatedBy
|
||||
.OnDelete(DeleteBehavior.Restrict); // 当 User (Creator) 被删除时,如果还有他/她创建的 Question,则会阻止删除。
|
||||
// 由于 CreatedBy 是 [Required],Prevent/Restrict 是一个安全的选择。
|
||||
|
||||
// ---
|
||||
// 配置 Question 到 AssignmentQuestion 的关系 (一对多)
|
||||
// 一个 Question 可以被多个 AssignmentQuestion 引用。
|
||||
//
|
||||
// 这个关系的外键配置通常在 "多" 的一方(`AssignmentQuestion` 实体)进行。
|
||||
// 假设 `AssignmentQuestion` 实体有一个 `QuestionId` 外键和 `Question` 导航属性。
|
||||
builder.HasMany(q => q.AssignmentQuestions) // 当前 Question 有多个 AssignmentQuestion
|
||||
.WithOne(aq => aq.Question); // 每一个 AssignmentQuestion 都有一个 Question
|
||||
// .HasForeignKey(aq => aq.QuestionId); // 外键的配置应在 `AssignmentQuestionConfiguration` 中进行
|
||||
}
|
||||
}
|
||||
}
|
25
TechHelper.Server/Context/Configuration/RoleConfiguration.cs
Normal file
25
TechHelper.Server/Context/Configuration/RoleConfiguration.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
|
||||
public class RoleConfiguration : IEntityTypeConfiguration<IdentityRole<Guid>>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<IdentityRole<Guid>> builder)
|
||||
{
|
||||
builder.HasData(
|
||||
Enum.GetValues(typeof(UserRoles))
|
||||
.Cast<UserRoles>()
|
||||
.Select(roleEnum => new IdentityRole<Guid>
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = roleEnum.ToString(),
|
||||
NormalizedName = roleEnum.ToString().ToUpper()
|
||||
})
|
||||
.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,109 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class SubmissionConfiguration : IEntityTypeConfiguration<Submission>
|
||||
{
|
||||
public void Configure(EntityTypeBuilder<Submission> builder)
|
||||
{
|
||||
// 1. 设置表名
|
||||
builder.ToTable("submissions");
|
||||
|
||||
// 2. 设置主键
|
||||
builder.HasKey(s => s.Id);
|
||||
|
||||
// 3. 配置列名、必需性、精度及其他属性
|
||||
|
||||
// Id
|
||||
builder.Property(s => s.Id)
|
||||
.HasColumnName("id");
|
||||
|
||||
// AssignmentId
|
||||
builder.Property(s => s.AssignmentId)
|
||||
.HasColumnName("assignment_id")
|
||||
.IsRequired();
|
||||
|
||||
// StudentId
|
||||
builder.Property(s => s.StudentId)
|
||||
.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); // 应用精度设置
|
||||
|
||||
// OverallFeedback
|
||||
builder.Property(s => s.OverallFeedback)
|
||||
.HasColumnName("overall_feedback");
|
||||
|
||||
// GradedBy (现为 Guid? 类型)
|
||||
builder.Property(s => s.GradedBy)
|
||||
.HasColumnName("graded_by"); // 作为可空外键,不需要 IsRequired()
|
||||
|
||||
// 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); // <--- 应用最大长度
|
||||
|
||||
// 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
|
||||
.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` 中进行
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,105 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class SubmissionDetailConfiguration : IEntityTypeConfiguration<SubmissionDetail>
|
||||
{
|
||||
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); // 常用作软删除标记
|
||||
|
||||
// 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 (作为学生)
|
||||
.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
|
||||
.OnDelete(DeleteBehavior.Cascade); // 当 AssignmentQuestion 被删除时,相关的 SubmissionDetail 记录也级联删除。
|
||||
}
|
||||
}
|
||||
}
|
76
TechHelper.Server/Context/Configuration/UserConfiguration.cs
Normal file
76
TechHelper.Server/Context/Configuration/UserConfiguration.cs
Normal file
@@ -0,0 +1,76 @@
|
||||
using Entities.Contracts;
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Builders;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace TechHelper.Context.Configuration
|
||||
{
|
||||
public class UserConfiguration : IEntityTypeConfiguration<User>
|
||||
{
|
||||
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");
|
||||
|
||||
builder.Property(u => u.RefreshTokenExpiryTime)
|
||||
.HasColumnName("refresh_token_expiry_time");
|
||||
|
||||
builder.Property(u => u.IsDeleted)
|
||||
.HasColumnName("deleted")
|
||||
.HasDefaultValue(false); // 软删除标记,默认 false
|
||||
|
||||
// 配置导航属性 (User 作为关系的“一”或“主”方)
|
||||
|
||||
// User 作为老师,与 ClassTeacher 的关系 (一对多)
|
||||
builder.HasMany(u => u.TaughtClassesLink) // 一个 User (老师) 可以教授多个班级
|
||||
.WithOne(ct => ct.Teacher) // 一个 ClassTeacher 记录对应一个 Teacher
|
||||
.HasForeignKey(ct => ct.TeacherId) // 外键在 ClassTeacher.TeacherId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果老师有任教记录,则不允许删除
|
||||
|
||||
// User 作为学生,与 ClassStudent 的关系 (一对多)
|
||||
builder.HasMany(u => u.EnrolledClassesLink) // 一个 User (学生) 可以注册多个班级
|
||||
.WithOne(cs => cs.Student) // 一个 ClassStudent 记录对应一个 Student
|
||||
.HasForeignKey(cs => cs.StudentId) // 外键在 ClassStudent.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果学生有注册记录,则不允许删除
|
||||
|
||||
// User 作为创建者,与 Question 的关系 (一对多)
|
||||
builder.HasMany(u => u.CreatedQuestions) // 一个 User 可以创建多个题目
|
||||
.WithOne(q => q.Creator) // 一个 Question 对应一个 Creator
|
||||
.HasForeignKey(q => q.CreatedBy) // 外键在 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
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果创建者有作业,则不允许删除
|
||||
|
||||
// User 作为学生,与 SubmissionDetail 的关系 (一对多)
|
||||
// 尽管 SubmissionDetail 也可以通过 Submission 间接关联到 User,
|
||||
// 但这里提供了直接访问的导航属性,以方便直接查询学生的所有作答详情。
|
||||
builder.HasMany(u => u.SubmissionDetails) // 一个 User (学生) 可以有多个提交详情记录
|
||||
.WithOne(sd => sd.User) // 一个 SubmissionDetail 对应一个 User (学生)
|
||||
.HasForeignKey(sd => sd.StudentId) // 外键在 SubmissionDetail.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果学生有提交详情,则不允许删除
|
||||
|
||||
// User 作为学生,与 Submission 的关系 (一对多)
|
||||
builder.HasMany(u => u.SubmissionsAsStudent) // 一个 User (学生) 可以有多个提交记录
|
||||
.WithOne(s => s.Student) // 一个 Submission 对应一个 Student
|
||||
.HasForeignKey(s => s.StudentId) // 外键在 Submission.StudentId
|
||||
.OnDelete(DeleteBehavior.Restrict); // 限制删除:如果学生有提交记录,则不允许删除
|
||||
|
||||
// User 作为批改者,与 Submission 的关系 (一对多)
|
||||
builder.HasMany(u => u.GradedSubmissions) // 一个 User (批改者) 可以批改多个提交
|
||||
.WithOne(s => s.Grader) // 一个 Submission 对应一个 Grader
|
||||
.HasForeignKey(s => s.GradedBy) // 外键在 Submission.GradedBy
|
||||
.OnDelete(DeleteBehavior.SetNull); // 因为 GradedBy 是可空的,所以批改者删除时,设为 NULL
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user