Partial updates to JSONB columns
See original GitHub issueLet’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:
- Update only Customer name (it could be update from SomeEntity class)
- After changes are made call DbContext SaveChanges method
- 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:
- Created 3 years ago
- Comments:12 (7 by maintainers)
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:
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.Ah sorry, I misunderstood. There is no workaround currently, except for using raw SQL.