question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Partial updates to JSONB columns

See original GitHub issue

Let’s say that I have next model where Customer property is mapped to JSONB column type.

    public class SomeEntity
    {
        public int Id { get; set; }

        [Column(TypeName = "jsonb")]
        public Customer Customer { get; set; }
    }

    public class Customer    // Mapped to a JSON column in the table
    {
        public string Name { get; set; }
        public int Age { get; private set; }
        public List<string> Orders { get; private set; }

        public Customer(string name, int age, List<Order> orders)
        {
            Name = name;
            Age = age;
            Orders = orders;
        }

        private Customer()
        {
        }

        public void UpdateName(string name)
        {
               Name = name;
        }
    }

Is it possible to:

  1. Update only Customer name (it could be update from SomeEntity class)
  2. After changes are made call DbContext SaveChanges method
  3. Even if reference to the Customer is same, and only Name property is updated -> updated value is stored in database

As far as I see, in order to update Customer name and persist data in database I would need to change customer reference inside SomeEntity, something like: Customer = new Customer { Name = newName, Age = Customer.Age, Orders = Customer.Orders}

This is just simplified solution, but update process can become much more complex with more complex model. What if we have collection of customers mapped to JSONB column type and we want to update just name of particular customer?

        [Column(TypeName = "jsonb")]
        public List<Customer> Customer { get; set; }

To be more precise before step 2 is completed context change tracker shows that EntityState is Unchanged (and that is a reason why changes aren’t persisted). In some cases I can probably manually override EntityState, but is there a smarter way to do it?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:12 (7 by maintainers)

github_iconTop GitHub Comments

5reactions
rojicommented, Aug 14, 2020

It currently isn’t possible to make EF issue updates of fields within JSONB documents - EF only knows how to change the entire property, i.e. by sending the entire modified JSON document. This can indeed be less efficient, but otherwise is the same functionally. This could in theory be done by using PostgreSQL’s jsonb_set/jsonb_insert (see docs), but that would be quite a change in the EF update pipeline.

To make EF update the entire JSON document, you have to let EF know that the property has changed. EF usually auto-detects changes (by snapshotting the value when it’s loaded, and then comparing it when SaveChanges is called), but since JSON documents can be very big, and detecting changes would be bad for perf. However, you can still enable automatic change detection by setting up a value comparer on your JSON property.

For a perf-minded application, the best would be to manually tell EF that you’ve made a change:

ctx.Entry(someEntity).Property(e => e.Customer).IsModified = true;

After doing this, calling SaveChanges should generate an UPDATE to write the new document value.

Am going to keep this open to track partial updates to JSON documents (jsonb_set) although this really isn’t likely to be done anytime soon.

3reactions
rojicommented, Jun 18, 2021

Ah sorry, I misunderstood. There is no workaround currently, except for using raw SQL.

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to perform update operations on columns of type ...
If you're able to upgrade to Postgresql 9.5, the jsonb_set command is available, as others have mentioned. In each of the following SQL ......
Read more >
Postgres — partial update json object using jsonb_set()
For partial update, we do have a function which is quite handly jsonb_set. So, lets understand how this in-built function works. jsonb_set ...
Read more >
how to update a property value of a jsonb field?
There are two ways to accomplish this: Simply concatenating the new key/value pair: update the_table set attr = attr || '{"is_default": ...
Read more >
Updating JSON Data in PostgreSQL
Updating JSON Data in PostgreSQL. If you're storing JSON data in Postgres, you'll eventually need to update it. In this post, we'll talk ......
Read more >
Partial update of JSON values
This update can be performed as a partial update because it takes a JSON column (json_col), modifies one of its members, and then...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found