Проект "Отпуск сотрудников". Часть 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-канале.