Предположим, у нас есть простая модель сущности.
public class University
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Student> Students { get; set; }
public Employee()
{
Students = new HashSet<Student>();
}
}
public class Student
{
[Key]
public int Id { get; set; }
public int UniversityId { get; set; }
public string Name { get; set; }
public University University { get; set; }
}
И давайте предположим, что у нас уже есть следующие данные в наших таблицах:
University
Id: 1
Name: MIT
Student
Id: 1
UniversityId: 1
Name: Bob
-----------
Id: 2
UniversityId: 1
Name: Carl
Тогда у нас есть API, который должен обновить университет , И давайте предположим, что мы получили следующую модель с помощью этого API
University: {
Id: 1,
Name: MIT,
Students: [
{
Id: 1,
Name: Bobby
}
]
}
Кроме того, давайте предположим, что у нас есть стандартные модели представления для наших объектов, поэтому они будут выглядеть следующим образом:
public class UniversityVM
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<StudentVM> Students { get; set; }
public Employee()
{
Students = new List<Student>();
}
}
public class StudentVM
{
public int Id { get; set; }
public string Name { get; set; }
}
Эти представления модели сопоставляются с нашими сущностями с помощью некоторого преобразователя, например, Automapper, например:
CreateMap<StudentVM, Student>();
CreateMap<UniversityVM, University>();
Затем для его обновления мы напишем следующий код (предположим, что мы работаем в автономном сценарии)
public void Update (UniversityVM request) {
var existingUniversity = _context.Universities.Single(b => b.Id == request.Id);
_mapper.Map(request, existingUniversity);
_context.Update(existingUniversity);
_context.SaveChanges();
}
Фактически мы заменили existingUniversity.Students
на request.Students
и затем сохранили его. Таким образом, ожидаемый результат должен состоять в том, что все ученики, у которых нет указанного идентификатора, должны быть сохранены (так будет), все ученики, у которых указан идентификатор и уже существует, будут обновлены (и так будет) наконец, все остальные связанные студенты, которые существовали до этого запроса, но отсутствуют в request.Students
, должны быть удалены (и это не будет работать таким образом).
Если мы отладим это, мы обнаружим, что в * В университете 1024 * с идентификатором 1 будет обновлена коллекция студентов, поэтому теоретически контекст EF знает, что мы удалили существующих студентов из контекста.
Но почему он не удаляет тех студентов, которые не представлены в обновленном коллекция больше?
Эта проблема заставляет нас выполнять операцию удаления вручную, что увеличивает объем кода для записи.
Существует ли какой-либо существующий способ добиться "умного" обновления из коробки?
Умное обновление - это когда мы не пишем никакого кода, и по умолчанию будет следующее поведение:
Объекты в Будет создана вложенная коллекция, у которой нет указанного идентификатора. Существующие сущности во вложенной коллекции, представленные в новой коллекции, будут изменены. Существующие сущности во вложенной коллекции, которые не представлены в новой коллекции, будут удалены. Спасибо.