У меня следующий (упрощенный, но достаточно хороший, чтобы продемонстрировать проблему) запрос:
var schoolsQuery = _dbContext.Set<School>();
var schoolSubjectTeachersQuery = _dbContext.Set<SchoolSubjectTeacher>();
var teacherSubjectsQuery = _dbContext.Set<SubjectTeacher>();
var teachersQuery = _dbContext.Set<Teacher>();
var teacherPersonQuery = _dbContext.Set<PersonInfo>();
// projecting to a simplified, detached viewlist entity to collect minimum required fields only
// and to generate an optimal query with left joins
// many-to-many joins: schools -> school teacher subjects -> teacher subjects -> teachers -> teacher info to finally get schools with all unique teachers inside
var projected = (from s in schoolsQuery
join sst in schoolSubjectTeachersQuery on s.Id equals sst.SchoolId into schoolSubjectTeachers
from sstj in schoolSubjectTeachers.DefaultIfEmpty()
join ts in teacherSubjectsQuery on sstj.TeacherSubjectId equals ts.Id into teacherSubjects
from tsj in teacherSubjects.DefaultIfEmpty()
join t in teachersQuery on tsj.TeacherId equals t.Id into teachers
from tj in teachers.DefaultIfEmpty()
join tp in teacherPersonQuery on tj.PersonId equals tp.Id into teacherPersons
from tpj in teacherPersons.DefaultIfEmpty()
// ignore deleted teachers and school-teachersubject and teacher-subject links that are no longer active
where (sstj == null || !sstj.Isdeleted) &&
(tsj == null || !tsj.Isdeleted) &&
(tj == null || !tj.Isdeleted)
select new SimpleViewOfSchoolWithActiveTeachers
{
Id = s.Id,
SchoolName = s.SchoolName,
SchoolAddress = s.SchoolAddress,
// hacky - storing single teacher into the flat list
// TODO: redesign to make EF intelligently rearrange the flat list into hierarchy
// with all schools and nested teachers, if any
Teachers = tpj == null ? null : new List<SimpleViewOfActiveTeacher> { new ViewOfActiveTeacher {
Id = tj.Id, // id of the teacher record
PersonId = tpj.PersonId, // data from the person info record of the teacher
PersonFullName = tpj.PersonFullName // data from the person info record of the teacher
} }
});
var results = projected.ToList();
// got a flat list here with a school attached to every left-joined teacher
В общем, это работает - я получаю список всех школ и их учителей, но есть двапроблемы:
если один учитель преподаёт более одного предмета в одной и той же школе, запись повторяется дважды, потому что есть два школьных учителя, присоединяющихся к предмету учителя. Меня не волнуют предметы в этом конкретном запросе, поэтому мне нужны уникальные учителя для каждой школы
, очевидно, набор результатов плоский с повторением родительской школы для каждой записи о детях учителя
Я могу решить обе проблемы, перебирая результаты и перестраивая иерархию и пропуская дублирующих учителей в каждой школе.
Однако я надеялся, что есть более элегантное решение.
Есть ли что-то, что использует встроенные механизмы EntityFramework или Linq вместо ручной итерации и исправления иерархии набора результатов?