Как передать через метод POST сущности со связью Many-to-Many?
Проектирую MVC - приложение и возникли затруднения с добавлением данных в БД. Имею базу данных с 3 сущностями, между которыми связь Many-to-Many:
public class Employee
{
[Required] public long Id { get; set; }
[Required] public string Name { get; set; } = null!;
public ICollection<EmployeeSkill>? Skill { get; set; }
}
public class Skill
{
[Required] public long Id { get; set; }
[Required] public string Name { get; set; }
public ICollection<EmployeeSkill>? Employees { get; set; }
}
public class EmployeeSkill
{
[Required] public long EmployeeId { get; set; }
[Required,ForeignKey("EmployeeId")] public Employee Employee{ get; set; }
[Required] public long SkillId { get; set; }
[Required,ForeignKey("SkillId")] public Skill Skill{ get; set; }
[Required] public byte Level { get; set; }
}
Данные сущности необходимо передать в контроллер, в методе POST и создать далее соответствующие строки таблицы. Благодарю за ответы!
Ответы (1 шт):
Для создания этих сущностей вам нужно имя работника, название умения и уровень.
Создадим модель для них:
public class EmployeeSkillModel
{
public string EmployeeName { get; set; }
public string SkillName { get; set; }
public byte Level { get; set; }
}
Метод контроллера должен иметь параметр этого типа. Что-то вроде:
[HttpPost]
public ActionResult Create(EmployeeSkillModel employeeSkillModel)
Далее делаем валидацию (оставляю это вам) и создаём наши сущности:
var employee = new Employee { Name = employeeSkillModel.EmployeeName };
var skill = new Skill { Name = employeeSkillModel.SkillName };
var employeeSkill = new EmployeeSkill { Employee = employee, Skill = skill, Level = employeeSkillModel.Level };
db.EmployeeSkills.Add(employeeSkill);
db.SaveChanges();
Теперь немного выскажу свои мысли.
В ваших моделях Employee и Skill определены свойства-коллекции EmployeeSkill - это так называемые join entity (сущность соединения). Я бы порекомендовал сделать прямые навигационные свойства:
public class Employee
{
[Required] public long Id { get; set; }
[Required] public string Name { get; set; } = null!;
public ICollection<Skill>? Skills { get; set; }
public ICollection<EmployeeSkill>? EmployeeSkills { get; set; }
}
public class Skill
{
[Required] public long Id { get; set; }
[Required] public string Name { get; set; }
public ICollection<Employee>? Employees { get; set; }
public ICollection<EmployeeSkill>? EmployeeSkills { get; set; }
}
При этом join entity можно оставить, т. к. она у вас имеет payload (нагрузку) в виде свойства Level и к ней нужно иметь доступ.
Обратите внимание, что имена коллекций во множественном числе.
Вероятно, навыки в БД не должны повторяться. Для этого на свойство Name сущности Skill следует навесить ограничение уникальности: [Index(nameof(Name), IsUnique = true)]. То есть если в БД уже имеется Skill с каким-то названием, то не создавать новый, а использовать имеющийся.