Ответ
Связь "многие-ко-многим" (Many-to-Many) напрямую в реляционных БД не реализуется. Для нее требуется промежуточная таблица-связка (join table, junction table), которая хранит пары внешних ключей, связывающих записи из двух основных таблиц.
Схема на примере Students и Courses:
-- Основные таблицы
CREATE TABLE Students (
StudentId INT PRIMARY KEY,
Name NVARCHAR(100)
);
CREATE TABLE Courses (
CourseId INT PRIMARY KEY,
Title NVARCHAR(100)
);
-- Таблица-связка
CREATE TABLE StudentCourses (
StudentId INT,
CourseId INT,
EnrollmentDate DATE, -- Можно добавлять дополнительные атрибуты связи
PRIMARY KEY (StudentId, CourseId),
FOREIGN KEY (StudentId) REFERENCES Students(StudentId),
FOREIGN KEY (CourseId) REFERENCES Courses(CourseId)
);
Реализация в Entity Framework Core:
Способ 1: Явная сущность-связка (рекомендуется при наличии дополнительных данных в связи).
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
// Навигационное свойство к связующей сущности
public ICollection<StudentCourse> StudentCourses { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<StudentCourse> StudentCourses { get; set; }
}
// Явная сущность-связка
public class StudentCourse
{
public int StudentId { get; set; }
public Student Student { get; set; }
public int CourseId { get; set; }
public Course Course { get; set; }
public DateTime EnrollmentDate { get; set; } // Доп. поле
}
Способ 2: Неявная связь (EF Core 5.0+). EF Core автоматически создаст таблицу-связку.
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Course> Courses { get; set; } // Прямая навигация
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public ICollection<Student> Students { get; set; } // Прямая навигация
}
// Настройка в DbContext (Fluent API):
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Student>()
.HasMany(s => s.Courses)
.WithMany(c => c.Students)
.UsingEntity(j => j.ToTable("StudentCourses")); // Опционально: имя таблицы
}
Запросы:
// Найти всех студентов на курсе
var studentsInMath = context.Courses
.Where(c => c.Title == "Math")
.SelectMany(c => c.Students)
.ToList();
// Найти все курсы студента
var johnsCourses = context.Students
.Where(s => s.Name == "John")
.SelectMany(s => s.Courses)
.ToList();