Как обновить сущность связанными данными (массивами) из настраиваемых объектов запроса / тела с состояниями (изменено, добавлено, удалено) в EF Core 3+? - PullRequest
0 голосов
/ 18 июня 2020

Упрощенные версии моих объектов:

public class CV 
{
  public int Id {get;set;}
  public string Name {get;set;}
  public List<Certificate> Certificates {get;set;}
  public List<Experience> Experiences {get;set;}
}
public class Certificate 
{
  public int Id {get;set;}
  public string Name {get;set;}
}
public class Experience 
{
  public int Id {get;set;}
  public string Name {get;set;}
  public List<SkillExperience> Skills {get;set;}
}
public class SkillExperience
{
  public int SkillId {get;set;}
  public int ExperienceId {get;set;}
  public bool isCore {get;set;}
}
public class Skill 
{
  public int Id {get;set;}
  public string Name {get;set;}
}

Из тела запроса (из внешнего интерфейса) приходит следующий объект (снова очень упрощенный):

public class CvRequest 
{
  public int Id {get;set;}
  public string Name {get;set;}
  public CertificateRequest Certificates {get;set;}
  public ExperienceRequest Experiences {get;set;}
}
public class CertificateRequest
{
  public List<Certificate> AddedCertificates {get;set;}
  public List<Certificate> ModifiedCertificates {get;set;}
  public List<int> RemovedCertificateIDs {get;set;}
}
// the ExperienceRequest is a little more complex because it has a many-to-many relationship, so I won't show it
// but it's similar, the question is related to it, but it has the same pattern of modified/added/removed

У меня Generi c Шаблон репозитория (архитектура), поэтому I l oop через Список добавленных сущностей и вызывает conext.Set.Add (entity), I l oop через Modified и вызывает Update, а I l oop через удаленные ID и вызовите Remove по ID.

Проблема / вопрос:

Проблема в том, что я обращаюсь к CV с помощью .Include (cv => cv.Certificate) и всех связанных с этим данных путь. Затем я вызываю cvRepository.Update(cvRequest.ToEntity<CV>()); и , он работает , но затем, когда я звоню certificateRepository.Update(new Certificate(){...});, он говорит следующее:

System.InvalidOperationException: The instance of entity type 'Certificate' cannot be tracked because another instance with the key value '{Id: 5}' is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached.

Поскольку это связанные данные с уже отслеживаемым объектом, я могу ' т обновлять его самостоятельно. Я не могу cv.Certificates.Update (сертификат) или что-то в этом роде, у меня есть доступ только к DbSet напрямую. Пытался сделать {context_name}.Entry(entity).State = EntityState.Detached; Еще пробовал AsNoTracking.

А как насчет «многие ко многим»? Там еще хуже. Существует более глубокое управление вложением и отслеживанием.

А что насчет этого?

Как лучше всего обновить связанные данные объекта (и связанные данные связанных данных) в EF Core 3+?

Следует ли мне использовать {context_name}.Entry(entity).CurrentValues.SetValues(modifiedEntity); вместо Update(modifiedEntity);?

1 Ответ

0 голосов
/ 18 июня 2020

Я думаю, что проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь отследить сертификат с ID = 5 во второй раз, хотя он уже отслеживается с помощью вызова

certificateRepository.Update(new Certificate(){...});

По сути, он уже загружен и отслеживается с помощью .Include (cv => cv.Certificate) , и вы пытаетесь отслеживать его еще раз, создавая новый объект и вызывая Update в своем репозитории.

В этом случае вы можете манипулировать Сертификат, который загружается с cvRequest и вызывает SaveChanges без явного вызова «Update» для нового объекта сущности. EF Core будет управлять отслеживанием за вас, заметит, что оно было изменено, и обновит его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...