Как получить список учебных предметов для студента с помощью LINQ to SQL?
Есть, примерно, такая схема на C# и EntityFramework Core (v. 5.0.11):
// Студент
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public List<Subject> Subjects { get; set; }
}
// Учебный предмет
public class Subject
{
public int Id { get; set; }
public string Name { get; set; }
public Teacher Teacher { get; set; }
public int Hours { get; set; }
public List<Topic> Topics { get; set; }
}
// Учебный предмет, который выбрал студент
public class StudentSubject
{
public int StudentId { get; set; }
public int SubjectId { get; set; }
}
public class ApiDbContext : DbContext
{
// Список студентов
public DbSet<Student> Students { get; set;}
// Список учебных предметов
public DbSet<Subject> Subjects { get; set; }
// Список учебных предметов, выбранных студентами
public DbSet<StudentSubject> StudentSubjects { get; set; на }
//...
}
Как с помощью LINQ to SQL получить список предметов (Subjects в классе Student), которые выбрал студент? Понятно, что можно отфильтровать StudentSubjects по StudentId, а дальше?
P.S. Смущает то, что добавление связей "многие-ко-многим" приводит к добавлению дополнительных столбцов в таблицу БД, которые мне не нужны. Например, к таблице Subjects добавляется столбец StudentsId, а ведь один предмет могут выбрать несколько студентов.
Ответы (1 шт):
Для создания связи многие-ко-многим (many-to-many) достаточно в сущностях создать навигационные свойства-коллекции.
В классе Student делаем свойство List<Subject> Subjects.
В классе Subject делаем свойство List<Student> Students.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public List<Subject> Subjects { get; set; }
}
public class Subject
{
public int Id { get; set; }
public string Name { get; set; }
public List<Student> Students { get; set; }
}
public class ApiDbContext : DbContext
{
public DbSet<Student> Students { get; set; }
public DbSet<Subject> Subjects { get; set; }
// ...
}
При этом в БД автоматически будут созданы три таблицы: Students, Subjects и StudentSubject.
Теперь при добавлении сущностей в навигационные свойства связи между ними будут создавать тоже автоматически.
Возможно, у вас возникли сложности при получении связанных сущностей.
Например:
var student = db.Students.First(x => x.Name == "StudentA");
При выполнении этих запросов навигационные свойства окажутся пустыми. Дело в том, что связанные данные не загружаются по умолчанию. Это нужно сделать явно.
Loading Related Data
Самый распространённый способ - Eager Loading.
Для этого добавим метод Include в запрос:
var student = db.Students.Include(x => x.Subjects).First(x => x.Name == "StudentA");
Теперь предметы будут загружены.
Смущает то, что добавление связей "многие-ко-многим" приводит к добавлению дополнительных столбцов в таблицу БД, которые мне не нужны.
Это столбцы нужны движку реляционной СУБД. Без них невозможно связать данные из разных таблиц между собой.
Подробнее смотрите документацию:
Relationships: Many-to-many.
Changing Foreign Keys and Navigations: Many-to-many relationships.
Промежуточную сущность при желании можно создать и использовать. Но обычно это делают только при добавлении в неё дополнительных данных:
Join entities with payloads.
Можете ознакомиться с туториалом EF Core with MVC. В нём показан пример применения промежуточной сущности с полезной нагрузкой.
Many-to-Many relationships.