Changeset ea40556 for iknow-api/Data
- Timestamp:
- 09/15/26 21:15:53 (8 days ago)
- Branches:
- master
- Children:
- a12988e, c42181c
- Parents:
- 10009b9
- Location:
- iknow-api/Data
- Files:
-
- 1 added
- 1 edited
-
AppDbContext.cs (modified) (3 diffs)
-
PgEnumLabels.cs (added)
Legend:
- Unmodified
- Added
- Removed
-
iknow-api/Data/AppDbContext.cs
r10009b9 rea40556 4 4 namespace iknow_api.Data 5 5 { 6 /// <summary> 7 /// The schema is owned by sql/ddl.sql, not by EF migrations. Every entity 8 /// below is mapped explicitly onto the table and column names in that 9 /// script; nothing here may rely on EF naming conventions. 10 /// </summary> 6 11 public class AppDbContext : DbContext 7 12 { 13 /// <summary> 14 /// The schema created by sql/schema_creation.sql. Every table and enum 15 /// type is qualified with it, so nothing depends on search_path. 16 /// </summary> 17 public const string ProjectSchema = "project"; 18 8 19 public AppDbContext(DbContextOptions<AppDbContext> options) 9 20 : base(options) { } … … 12 23 public DbSet<ContactInfo> ContactInfo { get; set; } 13 24 public DbSet<HighSchool> HighSchool { get; set; } 14 public DbSet<EnrollmentInfo> EnrollmentInfo { get; set; }15 25 public DbSet<RefreshToken> RefreshToken { get; set; } 16 26 public DbSet<Subject> Subjects { get; set; } … … 27 37 public DbSet<ProfessorSubjects> ProfessorSubjects { get; set; } 28 38 29 30 39 protected override void OnModelCreating(ModelBuilder modelBuilder) 31 40 { 32 41 base.OnModelCreating(modelBuilder); 33 42 34 modelBuilder.Entity<Major>().HasData( 35 new Major { Id = 1, Name = "PIT" }, 36 new Major { Id = 2, Name = "SIIS" }, 37 new Major { Id = 3, Name = "SEIS" }, 38 new Major { Id = 4, Name = "KN" } 39 ); 40 41 42 // ------------------------- 43 // DependencySubject (self-referencing many-to-many) 44 // ------------------------- 45 modelBuilder.Entity<DependencySubject>() 46 .HasKey(ds => new { ds.SubjectId, ds.DependencyId }); 47 48 modelBuilder.Entity<DependencySubject>() 49 .HasOne(ds => ds.Subject) 50 .WithMany(s => s.Dependencies) 51 .HasForeignKey(ds => ds.SubjectId) 52 .OnDelete(DeleteBehavior.Restrict); 53 54 modelBuilder.Entity<DependencySubject>() 55 .HasOne(ds => ds.Dependency) 56 .WithMany(s => s.Dependents) 57 .HasForeignKey(ds => ds.DependencyId) 58 .OnDelete(DeleteBehavior.Restrict); 59 60 // ------------------------- 61 // MajorSubjects (many-to-many) 62 // ------------------------- 63 modelBuilder.Entity<MajorSubjects>() 64 .HasKey(ab => new { ab.MajorId, ab.SubjectId }); 65 66 modelBuilder.Entity<MajorSubjects>() 67 .HasOne(ab => ab.Majors) 68 .WithMany(a => a.Subjects) 69 .HasForeignKey(ab => ab.MajorId) 70 .OnDelete(DeleteBehavior.Cascade); 71 72 modelBuilder.Entity<MajorSubjects>() 73 .HasOne(ab => ab.Subjects) 74 .WithMany(b => b.Majors) 75 .HasForeignKey(ab => ab.SubjectId) 76 .OnDelete(DeleteBehavior.Cascade); 77 78 // ------------------------- 79 // UserDocuments (many-to-many) 80 // ------------------------- 81 modelBuilder.Entity<UserDocuments>() 82 .HasKey(ab => new { ab.UserId, ab.DocumentId }); 83 84 modelBuilder.Entity<UserDocuments>() 85 .HasOne(ab => ab.User) 86 .WithMany(a => a.Documents) 87 .HasForeignKey(ab => ab.UserId) 88 .OnDelete(DeleteBehavior.Cascade); 89 90 modelBuilder.Entity<UserDocuments>() 91 .HasOne(ab => ab.Documents) 92 .WithMany(b => b.User) 93 .HasForeignKey(ab => ab.DocumentId) 94 .OnDelete(DeleteBehavior.Cascade); 95 96 // ------------------------- 97 // Payment (user enrollment) 98 // ------------------------- 99 modelBuilder.Entity<Payment>() 100 .HasKey(p => p.Id); 101 102 modelBuilder.Entity<Payment>() 103 .HasOne(p => p.User) 104 .WithMany(u => u.EnrolledSemesters) 105 .HasForeignKey(p => p.UserId) 106 .OnDelete(DeleteBehavior.Cascade); 107 108 modelBuilder.Entity<Payment>() 109 .HasOne(p => p.EnrolledSemesters) 110 .WithMany(es => es.Users) 111 .HasForeignKey(p => p.EnrollmentInfoId) 112 .OnDelete(DeleteBehavior.Cascade); 113 114 // ------------------------- 115 // SemesterSubject (student enrollments and professor assignments) 116 // ------------------------- 117 modelBuilder.Entity<SemesterSubject>() 118 .HasKey(ss => ss.Id); // or composite key if you prefer {UserId, EnrolledSemesterId, SubjectId} 119 120 // Student enrollment 121 modelBuilder.Entity<SemesterSubject>() 122 .HasOne(ss => ss.User) 123 .WithMany(u => u.EnrolledSemesterUserSubjects) 124 .HasForeignKey(ss => ss.UserId) 125 .OnDelete(DeleteBehavior.Restrict); 126 127 // Professor teaching 128 modelBuilder.Entity<SemesterSubject>() 129 .HasOne(ss => ss.Professor) 130 .WithMany(u => u.TeachingSubjects) 131 .HasForeignKey(ss => ss.ProfessorId) 132 .OnDelete(DeleteBehavior.Restrict); 133 134 // Subject relation 135 modelBuilder.Entity<SemesterSubject>() 136 .HasOne(ss => ss.Subject) 137 .WithMany(s => s.SemesterSubjects) 138 .HasForeignKey(ss => ss.SubjectId) 139 .OnDelete(DeleteBehavior.Restrict); 140 141 // EnrolledSemester relation 142 modelBuilder.Entity<SemesterSubject>() 143 .HasOne(ss => ss.EnrolledSemester) 144 .WithMany(es => es.SemesterSubjects) 145 .HasForeignKey(ss => ss.EnrolledSemesterId) 146 .OnDelete(DeleteBehavior.Restrict); 147 148 // ------------------------- 149 // PassedSubject (one-to-one with SemesterSubject) 150 // ------------------------- 151 modelBuilder.Entity<PassedSubject>() 152 .HasKey(ps => ps.Id); 153 154 modelBuilder.Entity<PassedSubject>() 155 .HasOne(ps => ps.SemesterSubject) 156 .WithOne(ss => ss.PassedSubject) 157 .HasForeignKey<PassedSubject>(ps => ps.SemesterSubjectId) 158 .OnDelete(DeleteBehavior.Cascade); 159 160 // ------------------------- 161 // ActiveSemesters to EnrolledSemesters (one-to-many) 162 // ------------------------- 163 modelBuilder.Entity<EnrolledSemesters>() 164 .HasOne(es => es.Semester) 165 .WithMany(a => a.EnrolledSemesters) 166 .HasForeignKey(es => es.Id) 167 .OnDelete(DeleteBehavior.Restrict); 168 169 // ------------------------- 170 // ProfessorSubjects (many-to-many: Professor -> Semester -> Subject) 171 // ------------------------- 172 modelBuilder.Entity<ProfessorSubjects>() 173 .HasKey(ps => new { ps.ProfessorId, ps.SemesterId, ps.SubjectId }); 174 175 modelBuilder.Entity<ProfessorSubjects>() 176 .HasOne(ps => ps.Professor) 177 .WithMany() 178 .HasForeignKey(ps => ps.ProfessorId) 179 .OnDelete(DeleteBehavior.Cascade); 180 181 modelBuilder.Entity<ProfessorSubjects>() 182 .HasOne(ps => ps.Semester) 183 .WithMany() 184 .HasForeignKey(ps => ps.SemesterId) 185 .OnDelete(DeleteBehavior.Cascade); 186 187 modelBuilder.Entity<ProfessorSubjects>() 188 .HasOne(ps => ps.Subject) 189 .WithMany() 190 .HasForeignKey(ps => ps.SubjectId) 191 .OnDelete(DeleteBehavior.Cascade); 43 // The enum types themselves are declared in ddl.sql; this tells EF 44 // they exist so it does not try to treat the columns as text. 45 modelBuilder.HasPostgresEnum<UserRole>(ProjectSchema, "user_role"); 46 modelBuilder.HasPostgresEnum<HighSchoolType>(ProjectSchema, "hs_type"); 47 modelBuilder.HasPostgresEnum<Quota>(ProjectSchema, "quota_type"); 48 modelBuilder.HasPostgresEnum<sType>(ProjectSchema, "semester_type"); 49 modelBuilder.HasPostgresEnum<Grade>(ProjectSchema, "grade_type"); 50 51 // ------------------------- 52 // users 53 // ------------------------- 54 modelBuilder.Entity<User>(e => 55 { 56 e.ToTable("users", ProjectSchema); 57 e.HasKey(u => u.Id); 58 e.Property(u => u.Id).HasColumnName("id"); 59 e.Property(u => u.Name).HasColumnName("name"); 60 e.Property(u => u.EMBG).HasColumnName("embg"); 61 e.Property(u => u.Surname).HasColumnName("surname"); 62 e.Property(u => u.Index).HasColumnName("index"); 63 e.Property(u => u.Bday).HasColumnName("bday").HasColumnType("timestamp without time zone"); 64 e.Property(u => u.Email).HasColumnName("email"); 65 e.Property(u => u.PasswordHash).HasColumnName("password"); 66 e.Property(u => u.Role).HasColumnName("role"); 67 e.Property(u => u.Quota).HasColumnName("quota"); 68 e.Property(u => u.EnrollmentYear).HasColumnName("enrollment_year"); 69 e.Property(u => u.CreatedAt).HasColumnName("created_at").HasColumnType("timestamp without time zone"); 70 e.HasIndex(u => u.Email).IsUnique(); 71 }); 72 73 // ------------------------- 74 // high_school 75 // ------------------------- 76 modelBuilder.Entity<HighSchool>(e => 77 { 78 e.ToTable("high_school", ProjectSchema); 79 e.HasKey(h => h.Id); 80 e.Property(h => h.Id).HasColumnName("id"); 81 e.Property(h => h.UserId).HasColumnName("user_id"); 82 e.Property(h => h.GPA).HasColumnName("gpa"); 83 e.Property(h => h.HighSchoolType).HasColumnName("type"); 84 e.HasOne(h => h.User) 85 .WithOne(u => u.HighSchool) 86 .HasForeignKey<HighSchool>(h => h.UserId) 87 .OnDelete(DeleteBehavior.Restrict); 88 }); 89 90 // ------------------------- 91 // contact 92 // ------------------------- 93 modelBuilder.Entity<ContactInfo>(e => 94 { 95 e.ToTable("contact", ProjectSchema); 96 e.HasKey(c => c.Id); 97 e.Property(c => c.Id).HasColumnName("id"); 98 e.Property(c => c.UserId).HasColumnName("user_id"); 99 e.Property(c => c.City).HasColumnName("city"); 100 e.Property(c => c.Municipality).HasColumnName("municipality"); 101 e.Property(c => c.Address).HasColumnName("address"); 102 e.Property(c => c.PhoneNumber).HasColumnName("number"); 103 e.Property(c => c.MicrosoftEmail).HasColumnName("microsoft_email"); 104 e.HasOne(c => c.User) 105 .WithOne(u => u.ContactInfo) 106 .HasForeignKey<ContactInfo>(c => c.UserId) 107 .OnDelete(DeleteBehavior.Restrict); 108 }); 109 110 // ------------------------- 111 // major 112 // ------------------------- 113 modelBuilder.Entity<Major>(e => 114 { 115 e.ToTable("major", ProjectSchema); 116 e.HasKey(m => m.Id); 117 e.Property(m => m.Id).HasColumnName("id"); 118 e.Property(m => m.Name).HasColumnName("name"); 119 }); 120 121 // ------------------------- 122 // active_semesters 123 // ------------------------- 124 modelBuilder.Entity<ActiveSemesters>(e => 125 { 126 e.ToTable("active_semesters", ProjectSchema); 127 e.HasKey(a => a.Id); 128 e.Property(a => a.Id).HasColumnName("id"); 129 e.Property(a => a.Year).HasColumnName("year"); 130 e.Property(a => a.Type).HasColumnName("type"); 131 }); 132 133 // ------------------------- 134 // subjects 135 // ------------------------- 136 modelBuilder.Entity<Subject>(e => 137 { 138 e.ToTable("subjects", ProjectSchema); 139 e.HasKey(s => s.Id); 140 e.Property(s => s.Id).HasColumnName("id"); 141 e.Property(s => s.Name).HasColumnName("name"); 142 e.Property(s => s.Code).HasColumnName("code"); 143 e.Property(s => s.AwardedCredits).HasColumnName("awarded_credits"); 144 e.Property(s => s.DependencyCredit).HasColumnName("dependency_credit"); 145 }); 146 147 // ------------------------- 148 // enrolled_semesters 149 // ------------------------- 150 modelBuilder.Entity<EnrolledSemesters>(e => 151 { 152 e.ToTable("enrolled_semesters", ProjectSchema); 153 e.HasKey(es => es.Id); 154 e.Property(es => es.Id).HasColumnName("id"); 155 e.Property(es => es.UserId).HasColumnName("user_id"); 156 e.Property(es => es.QuotaType).HasColumnName("quota"); 157 e.Property(es => es.MajorId).HasColumnName("major_id"); 158 e.Property(es => es.Note).HasColumnName("note"); 159 e.Property(es => es.StudentComment).HasColumnName("student_comment"); 160 e.Property(es => es.CratedAt).HasColumnName("created_at").HasColumnType("timestamp without time zone"); 161 e.Property(es => es.LastChange).HasColumnName("last_change").HasColumnType("timestamp without time zone"); 162 e.Property(es => es.Verified).HasColumnName("completed").HasColumnType("timestamp without time zone"); 163 e.Property(es => es.SemesterId).HasColumnName("semester_id"); 164 165 e.HasOne(es => es.User) 166 .WithMany(u => u.Enrolments) 167 .HasForeignKey(es => es.UserId) 168 .OnDelete(DeleteBehavior.Restrict); 169 170 // Note: this deliberately keys off SemesterId. An earlier version 171 // pointed the foreign key at es.Id, which silently tied every 172 // enrolment to the semester that happened to share its id. 173 e.HasOne(es => es.Semester) 174 .WithMany(a => a.EnrolledSemesters) 175 .HasForeignKey(es => es.SemesterId) 176 .OnDelete(DeleteBehavior.Restrict); 177 178 e.HasOne(es => es.Major) 179 .WithMany() 180 .HasForeignKey(es => es.MajorId) 181 .OnDelete(DeleteBehavior.Restrict); 182 }); 183 184 // ------------------------- 185 // semesters_subjects 186 // ------------------------- 187 modelBuilder.Entity<SemesterSubject>(e => 188 { 189 e.ToTable("semesters_subjects", ProjectSchema); 190 e.HasKey(ss => ss.Id); 191 e.Property(ss => ss.Id).HasColumnName("id"); 192 e.Property(ss => ss.EnrolledSemesterId).HasColumnName("enrolled_semesters_id"); 193 e.Property(ss => ss.SubjectId).HasColumnName("subjects_id"); 194 e.Property(ss => ss.ProfessorId).HasColumnName("professor_id"); 195 e.Property(ss => ss.Signature).HasColumnName("signature"); 196 197 e.HasOne(ss => ss.Professor) 198 .WithMany(u => u.TeachingSubjects) 199 .HasForeignKey(ss => ss.ProfessorId) 200 .OnDelete(DeleteBehavior.Restrict); 201 202 e.HasOne(ss => ss.Subject) 203 .WithMany(s => s.SemesterSubjects) 204 .HasForeignKey(ss => ss.SubjectId) 205 .OnDelete(DeleteBehavior.Restrict); 206 207 e.HasOne(ss => ss.EnrolledSemester) 208 .WithMany(es => es.SemesterSubjects) 209 .HasForeignKey(ss => ss.EnrolledSemesterId) 210 .OnDelete(DeleteBehavior.Restrict); 211 }); 212 213 // ------------------------- 214 // passed_subjects 215 // ------------------------- 216 modelBuilder.Entity<PassedSubject>(e => 217 { 218 e.ToTable("passed_subjects", ProjectSchema); 219 e.HasKey(ps => ps.Id); 220 e.Property(ps => ps.Id).HasColumnName("id"); 221 e.Property(ps => ps.SemesterSubjectId).HasColumnName("enrolled_id"); 222 e.Property(ps => ps.Grade).HasColumnName("grade"); 223 e.Property(ps => ps.DatePassed).HasColumnName("date_passed").HasColumnType("timestamp without time zone"); 224 225 e.HasOne(ps => ps.SemesterSubject) 226 .WithOne(ss => ss.PassedSubject) 227 .HasForeignKey<PassedSubject>(ps => ps.SemesterSubjectId) 228 .OnDelete(DeleteBehavior.Cascade); 229 }); 230 231 // ------------------------- 232 // documents 233 // ------------------------- 234 modelBuilder.Entity<Documents>(e => 235 { 236 e.ToTable("documents", ProjectSchema); 237 e.HasKey(d => d.Id); 238 e.Property(d => d.Id).HasColumnName("id"); 239 e.Property(d => d.Name).HasColumnName("type"); 240 e.Property(d => d.Body).HasColumnName("body"); 241 e.Property(d => d.Cost).HasColumnName("cost"); 242 }); 243 244 // ------------------------- 245 // user_documents 246 // ------------------------- 247 modelBuilder.Entity<UserDocuments>(e => 248 { 249 e.ToTable("user_documents", ProjectSchema); 250 e.HasKey(ud => new { ud.UserId, ud.DocumentId }); 251 e.Property(ud => ud.UserId).HasColumnName("user_id"); 252 e.Property(ud => ud.DocumentId).HasColumnName("document_id"); 253 254 e.HasOne(ud => ud.User) 255 .WithMany(u => u.Documents) 256 .HasForeignKey(ud => ud.UserId) 257 .OnDelete(DeleteBehavior.Cascade); 258 259 e.HasOne(ud => ud.Documents) 260 .WithMany(d => d.User) 261 .HasForeignKey(ud => ud.DocumentId) 262 .OnDelete(DeleteBehavior.Cascade); 263 }); 264 265 // ------------------------- 266 // token 267 // ------------------------- 268 modelBuilder.Entity<RefreshToken>(e => 269 { 270 e.ToTable("token", ProjectSchema); 271 e.HasKey(t => t.Id); 272 e.Property(t => t.Id).HasColumnName("id"); 273 e.Property(t => t.UserId).HasColumnName("user_id"); 274 e.Property(t => t.Token).HasColumnName("token"); 275 e.Property(t => t.ExpiresAt).HasColumnName("expires_at").HasColumnType("timestamp without time zone"); 276 e.Property(t => t.IsValid).HasColumnName("is_valid"); 277 278 e.HasOne(t => t.User) 279 .WithMany() 280 .HasForeignKey(t => t.UserId) 281 .OnDelete(DeleteBehavior.Cascade); 282 }); 283 284 // ------------------------- 285 // payment 286 // ------------------------- 287 modelBuilder.Entity<Payment>(e => 288 { 289 e.ToTable("payment", ProjectSchema); 290 e.HasKey(p => p.Id); 291 e.Property(p => p.Id).HasColumnName("id"); 292 e.Property(p => p.UserId).HasColumnName("user_id"); 293 e.Property(p => p.EnrollmentInfoId).HasColumnName("enrollment_id"); 294 e.Property(p => p.Amount).HasColumnName("amount"); 295 296 e.HasOne(p => p.User) 297 .WithMany(u => u.Payments) 298 .HasForeignKey(p => p.UserId) 299 .OnDelete(DeleteBehavior.Cascade); 300 301 e.HasOne(p => p.EnrolledSemesters) 302 .WithMany(es => es.Users) 303 .HasForeignKey(p => p.EnrollmentInfoId) 304 .OnDelete(DeleteBehavior.Cascade); 305 }); 306 307 // ------------------------- 308 // major_subjects 309 // ------------------------- 310 modelBuilder.Entity<MajorSubjects>(e => 311 { 312 e.ToTable("major_subjects", ProjectSchema); 313 e.HasKey(ms => new { ms.MajorId, ms.SubjectId }); 314 e.Property(ms => ms.MajorId).HasColumnName("major_id"); 315 e.Property(ms => ms.SubjectId).HasColumnName("subject_id"); 316 e.Property(ms => ms.MandatorySemester).HasColumnName("mandatory_semester"); 317 318 e.HasOne(ms => ms.Majors) 319 .WithMany(m => m.Subjects) 320 .HasForeignKey(ms => ms.MajorId) 321 .OnDelete(DeleteBehavior.Cascade); 322 323 e.HasOne(ms => ms.Subjects) 324 .WithMany(s => s.Majors) 325 .HasForeignKey(ms => ms.SubjectId) 326 .OnDelete(DeleteBehavior.Cascade); 327 }); 328 329 // ------------------------- 330 // dependency_subject 331 // ------------------------- 332 modelBuilder.Entity<DependencySubject>(e => 333 { 334 e.ToTable("dependency_subject", ProjectSchema); 335 e.HasKey(ds => new { ds.SubjectId, ds.DependencyId }); 336 e.Property(ds => ds.SubjectId).HasColumnName("subject_id"); 337 e.Property(ds => ds.DependencyId).HasColumnName("dependency_id"); 338 339 e.HasOne(ds => ds.Subject) 340 .WithMany(s => s.Dependencies) 341 .HasForeignKey(ds => ds.SubjectId) 342 .OnDelete(DeleteBehavior.Restrict); 343 344 e.HasOne(ds => ds.Dependency) 345 .WithMany(s => s.Dependents) 346 .HasForeignKey(ds => ds.DependencyId) 347 .OnDelete(DeleteBehavior.Restrict); 348 }); 349 350 // ------------------------- 351 // professour_subjects (spelling matches the table in ddl.sql) 352 // ------------------------- 353 modelBuilder.Entity<ProfessorSubjects>(e => 354 { 355 e.ToTable("professour_subjects", ProjectSchema); 356 e.HasKey(ps => new { ps.ProfessorId, ps.SemesterId, ps.SubjectId }); 357 e.Property(ps => ps.ProfessorId).HasColumnName("prof_id"); 358 e.Property(ps => ps.SemesterId).HasColumnName("active_semester_id"); 359 e.Property(ps => ps.SubjectId).HasColumnName("subject_id"); 360 361 e.HasOne(ps => ps.Professor) 362 .WithMany() 363 .HasForeignKey(ps => ps.ProfessorId) 364 .OnDelete(DeleteBehavior.Cascade); 365 366 e.HasOne(ps => ps.Semester) 367 .WithMany() 368 .HasForeignKey(ps => ps.SemesterId) 369 .OnDelete(DeleteBehavior.Cascade); 370 371 e.HasOne(ps => ps.Subject) 372 .WithMany() 373 .HasForeignKey(ps => ps.SubjectId) 374 .OnDelete(DeleteBehavior.Cascade); 375 }); 192 376 } 193 194 377 } 195 378 }
Note:
See TracChangeset
for help on using the changeset viewer.
