I'm using Simple Odata Client to perform CRUD operations in a WPF application.
I have a parent & a child entity:
public class Order
{
public int OrderId{get;set;}
public int Description{get;set;}
public ObservableCollection<OrderLine> OrderLines {get;set;}
}
public class OrderLine
{
public int OrderId{get;set;}
public int OrderLineId{get;set;}
public int ItenId{get;set;}
public int ItemDescription{get;set;}
public virtual Order Order {get;set;}
}
And I have a class for perform crud operation:
public class ManageOrders
{
//Implements INotifyPropertyChanged
Public Order Order;
public void Get()
{
this.Order = packages = await client
.For<Order>()
.ByKey(1001).
.Expand(x.OrderLines).
.FindEntriesAsync();
}
public void Save()
{
if("NEW")
{
// Add new item and save
}
if("MODIFIED")
{
// save modified item
}
}
public void Delete()
{
//Delete
}
}
I'm binding Parent entity properties to the header controls.
TextBox.Text = Order.Description;
and child entity to DataGrid.
DataGrid.ItemSource = Order.OrderLines;
When I click the GET Button, Order will be fetched from DB. Then I change the data in Order and OrderLines. Then I Delete a OrderLine and add two new OrderLines.
As I'm using ObservarbleCollection
, the changes will be automatically added to Source from UI.
Requirement
When I click SAVE button all the changes should be submitted to the server. (Batch request is preferred).
Question
How can I send only changed entities to the server through a PATCH request, without sending unmodified properties both in header and lines?
What you are asking for here is IMO the Holy Grail of web services and client-side frameworks.
Patch in OData makes it possible and simple to receive and process only changed properties for an object.
However it is up to the client to build the data packet appropriately, that can be done in 1 of two ways:
Before sending, the client should compare the data to send against the data that was last retrieved to determine the properties that have changed.
If the data on the client is wrapped in some kind of view model the view model could track (or watch) changes made to the properties.
Then on send, the client side must use this information to build a Delta of the object graph.
You haven't included any information on how you are generating your URIs to the backend service, so I don't want to guess but what ever the mechanism, 1 of the 2 strategies above will need to be implemented.
If your backend is an OData v4 service then you may find the OData Client package a helpful place to start. See OData Client library for .NET and the following to generate the client side object graphs: OData v4 Client Code Generator. You can use this against any service that implements the OData v4 specification, not only when you control the code for the backend.
For an example of usage of the generated classes see this SO question: What is the correct way to call patch from an odata client in web api 2 Or follow one of my unit tests:
Notice here to get the client to only send the modified properties are using a Microsoft.OData.Client.DataServiceCollection which inherits from ObservableCollection, but has the additional benefits of keeping an internal track of the changes to the objects in it's query. see DataServiceCollection Class.
That's the official MS way to interact with OData v4 services from C# code. The beauty of the T4 templates is that you can customize the template where needed or extend the generated partial classes so that your business logic does not get overridden when the classes are re-generated
You can roll your own mechanism to support this if you want, just remember the two options, either track the changes as they happen, or use comparison before save to identify which fields have changed.