Итак, у вас есть студенты и курсы. Каждый студент посещает ноль или более курсов. Я думаю, что курсы посещают ноль или больше студентов (многие ко многим). Мне кажется, вы разработали так, чтобы каждый курс посещал ровно один студент (один-ко-многим).
Если вы действительно рассчитывали один-ко-многим, ваш курс курса должен немного измениться:
class Course
{
public int Id {get; set;}
public DateTime CourseDate {get; set;}
...
public int StudentId {get; set;} // <======= !!!
public virtual Student Student {get; set;}
}
Вернемся к вашей проблеме
Вы написали:
Я хочу получить список студентов, у которых завтра курс и которые только что пройдут через список дочерних элементов.
Из ваших примеров кажется, что вы хотите, чтобы все студенты, у которых завтра будет хотя бы один курс, вместе со всеми курсами, которые этот студент будет завтра.
Обычно, когда с использованием структуры сущностей было бы достаточно использовать virtual ICollections
, как вы:
DateTime tomorrow = ...
var studentsWithCoursesOnDate = dbContext.Students.Select(student => new
{
// Select only the properties that you plan to use:
Id = student.Id,
Name = student.Name,
...
CoursesOnDate = student.Courses
.Where(course => course.CourseDate == tomorrow)
.Select(course => new
{
// again: only the properties that you plan to use
Id = course.Id,
Title = course.Title,
...
// not needed, you know the value
// StudentId = course.StudentId,
})
.ToList(),
})
.ToList();
Это должно работать с полной структурой сущностей. Entity framework знает отношения между таблицами и выполнит для вас правильный GroupJoin. Я слышал, что вы не можете использовать виртуальные ICollections в EF-core, я не проверял это.
Если вы хотите сделать GroupJoin самостоятельно:
DateTime tomorrow = ...
IQueryable<Course> tomorrowCourses = dbContext.Courses
.Where(course => course.CourseDate == tomorrow);
var studentsWithCoursesOnDate = dbContext.Students
.GroupJoin(tomorrowCourses, // GroupJoin Students and tomorrow's Courses
student => student.Id, // from every Student take the Id
course => course.StudentId, // from every Course take the foreign key
(student, coursesOfThisStudent) => new // when they match, make one new object
{
// again: select only the properties that you plan to use:
Id = student.Id,
Name = student.Name,
...
CoursesOnDate = coursesOfThisStudent.Select(course => new
{
// again: only the properties that you plan to use
Id = course.Id,
Title = course.Title,
...
})
.ToList(),
})
.ToList();
Примечание: идентификатор coursesOfThisStudent
на самом деле содержит только завтрашние курсы этого студента, но это сделало бы идентификатор излишне длинным.
Я использую Select, потому что Include извлекает все столбцы соответствующих строк данных, включая внешние ключи и другие данные которую вы, возможно, не собираетесь использовать прямо сейчас. Включить редко бывает эффективным.
При запросе данных всегда используйте Select
для выбора нужных значений. Используйте «Включить», только если вы планируете изменить (обновить) полученные данные.