4

I am trying to use Json patches to update entities stored in an Entity Framework data context.

I have entity classes like so -

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; }
}

To apply the patch onto a Customer object, I query the source from the data context, then apply the patch, like so -

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

patch.ApplyTo(entity);

dataContext.SaveChanges();

Where patch consists of -

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

This works fine for simple updates on the source object, the problem arises when I want to patch onto the linked entities, consider the following patch

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

The first issue that I am faced with is -

The target location specified by path segment '0' was not found

The only way around this I have found is to call the alter the way of querying the entity from the context to -

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

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

Which is less than ideal, as I don't like the idea of querying data to update it. I'm wondering if there is a cleaner approach to this.

Brendan
  • 3,415
  • 24
  • 26
  • After extensive searching, this approach appeared to be the most sound. – Brendan Mar 26 '19 at 00:02
  • 1
    Note that the use of OrderBy relies on Quotes being backed by a List<> rather than a HashSet<>. – Aaron Queenan Nov 20 '20 at 03:16
  • I think the reason is at run time, customer's quotes is a HashSet. If you change them to List, that may work. You can have something like `this.Quotes = new List();` in Customer contructor. – tala9999 Apr 14 '23 at 21:01

1 Answers1

0

This is the solution I landed on - https://gist.github.com/brendanmckenzie/a50f4eb7d5913372d01fef8e73c5dc9b

The code handles creating and updating entities stored in Entity Framework. Patching works well as EF tracks the changes applied by JsonPatch.

There is some additional code in there that's a bit messy (NormaliseOperations) that helps deal with linked entities; i.e., example if Quote referenced another entity.

Brendan
  • 3,415
  • 24
  • 26