76 lines
3.2 KiB
C#
76 lines
3.2 KiB
C#
|
|
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<Enrollment?> GetByIdAsync(int id, CancellationToken ct = default) =>
|
||
|
|
await context.Enrollments.FindAsync([id], ct);
|
||
|
|
|
||
|
|
public async Task<Enrollment?> GetByStudentAndSubjectAsync(int studentId, int subjectId, CancellationToken ct = default) =>
|
||
|
|
await context.Enrollments
|
||
|
|
.FirstOrDefaultAsync(e => e.StudentId == studentId && e.SubjectId == subjectId, ct);
|
||
|
|
|
||
|
|
public async Task<IReadOnlyList<Enrollment>> 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<IReadOnlyList<Enrollment>> GetBySubjectIdAsync(int subjectId, CancellationToken ct = default) =>
|
||
|
|
await context.Enrollments
|
||
|
|
.Include(e => e.Student)
|
||
|
|
.Where(e => e.SubjectId == subjectId)
|
||
|
|
.AsNoTracking()
|
||
|
|
.ToListAsync(ct);
|
||
|
|
|
||
|
|
public async Task<IReadOnlyList<Student>> 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<IReadOnlyDictionary<int, IReadOnlyList<Student>>> GetClassmatesBatchAsync(
|
||
|
|
int studentId, IEnumerable<int> subjectIds, CancellationToken ct = default)
|
||
|
|
{
|
||
|
|
var subjectIdList = subjectIds.ToList();
|
||
|
|
if (subjectIdList.Count == 0)
|
||
|
|
return new Dictionary<int, IReadOnlyList<Student>>();
|
||
|
|
|
||
|
|
// 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<Student>)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);
|
||
|
|
}
|