namespace Adapters.Driven.Persistence.Repositories; using Adapters.Driven.Persistence.Context; using Domain.Entities; using Domain.Ports.Repositories; using Microsoft.EntityFrameworkCore; public class EnrollmentRepository(AppDbContext context) : IEnrollmentRepository { public async Task GetByIdAsync(int id, CancellationToken ct = default) => await context.Enrollments.FindAsync([id], ct); public async Task GetByStudentAndSubjectAsync(int studentId, int subjectId, CancellationToken ct = default) => await context.Enrollments .FirstOrDefaultAsync(e => e.StudentId == studentId && e.SubjectId == subjectId, ct); public async Task> GetByStudentIdAsync(int studentId, CancellationToken ct = default) => await context.Enrollments .Include(e => e.Subject) .ThenInclude(s => s.Professor) .Where(e => e.StudentId == studentId) .AsNoTracking() .ToListAsync(ct); public async Task> GetBySubjectIdAsync(int subjectId, CancellationToken ct = default) => await context.Enrollments .Include(e => e.Student) .Where(e => e.SubjectId == subjectId) .AsNoTracking() .ToListAsync(ct); public async Task> GetClassmatesAsync(int studentId, int subjectId, CancellationToken ct = default) => await context.Enrollments .Where(e => e.SubjectId == subjectId && e.StudentId != studentId) .Select(e => e.Student) .AsNoTracking() .ToListAsync(ct); public async Task>> GetClassmatesBatchAsync( int studentId, IEnumerable subjectIds, CancellationToken ct = default) { var subjectIdList = subjectIds.ToList(); if (subjectIdList.Count == 0) return new Dictionary>(); // Single query to get all classmates for all subjects var enrollments = await context.Enrollments .Where(e => subjectIdList.Contains(e.SubjectId) && e.StudentId != studentId) .Select(e => new { e.SubjectId, e.Student.Id, e.Student.Name }) .AsNoTracking() .ToListAsync(ct); // Group by SubjectId and project to Student (minimal data needed) return enrollments .GroupBy(e => e.SubjectId) .ToDictionary( g => g.Key, g => (IReadOnlyList)g .Select(e => CreateMinimalStudent(e.Id, e.Name)) .ToList()); } private static Student CreateMinimalStudent(int id, string name) { // Use reflection to set Id since it's private set var student = (Student)System.Runtime.CompilerServices.RuntimeHelpers .GetUninitializedObject(typeof(Student)); typeof(Student).GetProperty("Id")!.SetValue(student, id); typeof(Student).GetProperty("Name")!.SetValue(student, name); return student; } public void Add(Enrollment enrollment) => context.Enrollments.Add(enrollment); public void Delete(Enrollment enrollment) => context.Enrollments.Remove(enrollment); }