JsonPatchDocument на сложный отслеживаемый объект Entity Framework

#c# #entity-framework #json-patch

#c# #entity-framework #json-patch

Вопрос:

Я пытаюсь использовать исправления Json для обновления объектов, хранящихся в контексте данных Entity Framework.

У меня есть классы сущностей, подобные таким —

 public class Customer
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public virtual ICollection<Quote> Quotes { get; set; }
}

public class Quote
{
    public Guid Id { get; set; }

    public int Order { get; set; }

    public string Status { get; set; }
}
  

Чтобы применить исправление к Customer объекту, я запрашиваю источник из контекста данных, затем применяю исправление, вот так —

 var entity = dataContext.Customers.Find(id);

patch.ApplyTo(entity);

dataContext.SaveChanges();
  

Где patch состоит из —

 [{ "op": "replace", "path": "/name", "value": "new name" }]
  

Это отлично работает для простых обновлений исходного объекта, проблема возникает, когда я хочу исправить связанные объекты, рассмотрим следующий патч

 [{ "op": "replace", "path": "/quotes/0/status", "value": "Closed" }]
  

Первая проблема, с которой я столкнулся, это —

Целевое местоположение, указанное в сегменте пути ‘0’, не было найдено

Единственный способ обойти это, который я нашел, — вызвать alter способ запроса объекта из контекста к —

 var entity = dataContext.Customers
    .Include(ent => ent.Quotes)
    .SingleOrDefault(ent => ent.Id == id);

entity.Quotes = entity.Quotes.OrderBy(ent => ent.Order).ToList);
  

Что далеко не идеально, поскольку мне не нравится идея запроса данных для их обновления. Мне интересно, есть ли более чистый подход к этому.

Комментарии:

1. После тщательного поиска этот подход оказался наиболее разумным.

2. Обратите внимание, что использование OrderBy основывается на кавычках, поддерживаемых списком<>, а не HashSet<> .

3. Я думаю, причина в том, что во время выполнения котировки клиента являются хэш-набором. Если вы измените их на List, это может сработать. У вас может быть что-то подобное this.Quotes = new List<Quote>(); в Customer constructor.

Ответ №1:

Это решение, на котором я остановился — https://gist.github.com/brendanmckenzie/a50f4eb7d5913372d01fef8e73c5dc9b

Код обрабатывает создание и обновление объектов, хранящихся в Entity Framework. Исправление работает хорошо, поскольку EF отслеживает изменения, применяемые JsonPatch.

Там есть некоторый дополнительный код, который немного запутан ( NormaliseOperations ), который помогает работать со связанными объектами; т. Е., например, если Quote ссылается на другой объект.