Ошибка EntityFramework при сохранении записи со списком дочерних записей - PullRequest
0 голосов
/ 25 мая 2020

В моем ASP. NET Core мы используем EF Core. При сохранении записи, имеющей список дочерних записей, мы получаем следующую ошибку:

Экземпляр типа сущности Child не может быть отслежен, потому что другой экземпляр с таким же значением ключа для {'Id'} уже существует. отслеживается.

Пошагово:
1. получить запись из контроллера и передать ее представлению (представление имеет)
2. обновить некоторые свойства с помощью формы html
3. нажмите "Сохранить".
4. Модель перехвата передана в методе сохранения контроллера. Получите исходный элемент из БД и сохраните изменения (сделанные через форму)
5. вызовите обновление / сохранение в репозитории

Упрощенный код ниже:

// Get the record from the database
var record = _dbContext.Parents
    .Include(x => p.SomeOtherObject)
    .Include(x => x.ListChildren)
    .FirstOrDefault(x => x.IdParent == id);

// then we do some changes to Parent and ListChildren
// we do not do any changes to SomeOtherObject!!!

// save changes
_dbContext.Update(record);
_dbContext.SaveChanges();

// definition of entities
public class Parent
{
    public int IdParent { get; set; }
    public string Name {get; set;}
    public string Surname {get; set;}

    public int IdSomeOtherObject { get; set; }
    [ForeignKey("IdSomeOtherObject")]
    public virtual SomeOtherObject SomeOtherObject { get; set; }

    public virtual List<Child> ListChildren { get; set; }
}

public class Child
{
    public int IdChild { get; set; }
    public int IdParent { get; set;}
    public string Name { get; set; }
}

public class SomeOtherObject
{
    public int IdSomeOtherObject { get; set; }
    public string PropertiesBlahBla { get; set; }
}

Теперь я знаем, что мы можем добавить .AsNoTracking() к операции Get, но тогда проблема в том, что при сохранении Parent EntityFramework будет выполнять и UPDATE SQL оператор даже для SomeOtherObject (который не был изменен ни в одном способ), и это неприемлемо для нашего сценария данных / ввода.

Есть ли другой способ передать эту ошибку?

1 Ответ

1 голос
/ 25 мая 2020

Попробуйте удалить _dbContext.Update(record);. Ваши объекты уже должны отслеживаться, поэтому изменения должны быть сохранены.

As Update docs state:

Начинает отслеживать данную сущность и записи, доступные из данный объект использует состояние Modified по умолчанию

Таким образом, кажется, что в этом сценарии он не нужен.

UPD

Во время при обсуждениях в чате было обнаружено, что отслеживаемая дочерняя коллекция была заменена следующим образом:

record.ListChildren = someModel.ListChildren.Where(...).ToList()

В результате были добавлены элементы с уже отслеживаемыми идентификаторами. Таким образом, ListChildren следует обновить с сохранением уже отслеженных элементов, например, рекомендованных здесь .

...