namespace Adapters.Driven.Persistence.Repositories;
using Adapters.Driven.Persistence.Context;
using Domain.Entities;
using Domain.Ports.Repositories;
using Domain.ReadModels;
using Microsoft.EntityFrameworkCore;
///
/// EF Core implementation of .
///
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 => new ClassmateInfo(e.Student.Id, e.Student.Name))
.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 - projects directly to ClassmateInfo
// Note: AsNoTracking is not needed for projections (Select) as they're not tracked by default
var enrollments = await context.Enrollments
.Where(e => subjectIdList.Contains(e.SubjectId) && e.StudentId != studentId)
.Select(e => new { e.SubjectId, Classmate = new ClassmateInfo(e.Student.Id, e.Student.Name) })
.ToListAsync(ct);
// Group by SubjectId
return enrollments
.GroupBy(e => e.SubjectId)
.ToDictionary(
g => g.Key,
g => (IReadOnlyList)g.Select(e => e.Classmate).ToList());
}
public void Add(Enrollment enrollment) => context.Enrollments.Add(enrollment);
public void Delete(Enrollment enrollment) => context.Enrollments.Remove(enrollment);
}