Проект "Отпуск сотрудников". Часть 2, хранилище и контроллер.
!!НАШ БЛОГ ПЕРЕЕХАЛ!!
Мы создали свой сайт! Все материалы, опубликованные в этом блоге, переехали туда.
Наш новый сайт maddevelop.ru
Создадим интерфейс IEmployeeRepository, в котором будут свойства с названиями таблиц из базы данных, а также методы для добавления и удаления элементов в таблицы.
public interface IEmployeeRepository { IEnumerable<Employee> Employees { get; } IEnumerable<Vacation> Vacations { get; } IEnumerable<Color> Colors { get; } Employee AddEmployee(Employee employee); void DeleteEmployee(int id); void AddVacation(int employeeId, Vacation vacation); void DeleteVacation(int employeeId, int vacationId); }
Определим класс EFEmployeeRepository, реализующий интерфейс IEmployeeRepository.
public class EFEmployeeRepository : IEmployeeRepository { private ApplicationDbContext context; public EFEmployeeRepository(ApplicationDbContext ctx) { context = ctx; } public IEnumerable<Color> Colors => context.Colors; public IEnumerable<Employee> Employees => context.Employees.Include(v => v.Vacations); public IEnumerable<Vacation> Vacations => context.Vacations; ..... }
Так как между таблицами базы данных Employees и Vacations имеется связь "один-ко-многим", то вместе со списком сотрудников требуется подгружать список отпусков, используя метод Include().
public IEnumerable<Employee> Employees => context.Employees.Include(v => v.Vacations);
Нам не требуется смотреть список сотрудников, цвета которых в сводной таблице окрашиваются одним цветом, поэтому просто получаем список цветов, без Include().
public IEnumerable<Color> Colors => context.Colors;
Методы добавления и удаления сущностей опишем так:
public Employee AddEmployee(Employee employee) { context.Employees.Add(employee); context.SaveChanges(); return employee; } public void DeleteEmployee(int id) { Employee deletedEmployee = context.Employees.FirstOrDefault(e => e.EmployeeId == id); if (deletedEmployee != null) { context.Employees.Remove(deletedEmployee); context.SaveChanges(); } } public void AddVacation(int employeeId, Vacation vacation) { Employee changedEmployee = context.Employees .FirstOrDefault(e => e.EmployeeId == employeeId); if (changedEmployee != null) { changedEmployee.Vacations.Add(vacation); context.SaveChanges(); } } public void DeleteVacation(int employeeId, int vacationId) { Employee changedEmployee = context.Employees .FirstOrDefault(e => e.EmployeeId == employeeId); if (changedEmployee != null) { Vacation deletedVacation = changedEmployee.Vacations .FirstOrDefault(v => v.VacationId == vacationId); if (deletedVacation != null) { changedEmployee.Vacations.Remove(deletedVacation); context.SaveChanges(); } } }
Теперь реализуем API-контроллер.
[Route("api/[controller]")] [ApiController] public class ValuesController : ControllerBase { private IEmployeeRepository employeeRepository; public ValuesController(IEmployeeRepository repo) { employeeRepository = repo; } public IEnumerable<Employee> GetEmployees() { return employeeRepository.Employees; } [HttpGet("colors")] public IEnumerable<Color> GetColors() { return employeeRepository.Colors; } [HttpPost] public Employee PostEmployee([FromBody]Employee employee) { return employeeRepository.AddEmployee(employee); } [HttpDelete("{id}")] public void DeleteEmployee(int id) { employeeRepository.DeleteEmployee(id); } [HttpPost("vacation")] public void AddVacation([FromBody]VacationViewModel vacationVM) { employeeRepository.AddVacation(vacationVM.EmployeeId, vacationVM.Vacation); } [HttpDelete("{idE}/{idV}")] public void DeleteVacation(int idE, int idV) { employeeRepository.DeleteVacation(idE, idV); } }
Для пояснения работы контроллера приведём таблицу, в которой для каждого маршрута приведён метод запроса и метод, который этим запросом вызывается.
Стоит отметить, что для добавления нового отпуска у сотрудника требуется передавать в контроллер идентификатор сотрудника и класс нового отпуска. Для передачи двух объектов используется вспомогательный класс.
public class VacationViewModel { public int EmployeeId { get; set; } public Vacation Vacation { get; set; } }
На этом разработка серверной части закончена. В следующих частях будет описан интерфейс пользователя.
Ещё больше интересной информации на нашем Telegram-канале.