April 9th, 2014
0 reactions

[Tutorial & Sample] Client Property Tracking for PATCH

 

In OData Client for .NET 6.2.0, we enabled the top level property tracking on client side when sending a PATCH. This feature allows client to send only updated properties, instead of the entire object to server.

The top level property tracking means the client will only track the highest level properties in the class hierarchy. In other words, if customer is updating a property under a complex type property, or an item in a collection property under an entity, the client will send the entire complex type property (including unchanged properties under the complex property) or the entire collection (including unchanged items in the collection) to the server.

In implementing property tracking, we start by creating a DataServiceCollection instance. DataServiceCollection helps to track all the properties. For more information about DataServiceCollection, See “Binding Data to Controls (WCF Data Services)”.

Let’s move to a real example to explain how to do it.

Service EDM model

http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/

Following sample code will base on this model.

Client Code

You can read “How to use OData Client Code Generator to generate client-side proxy class” for generating client-side proxy class.

Now, we will show you how to enable property tracking when doing a PATCH.

1. We need a DataServiceCollection which will handle property tracking.

DataServiceCollection<Product> products = new DataServiceCollection<Product>(dataServiceContext.Products.Where(p => p.ID == 0));

2. Update the property

products[0].Price = 3.0;

3. Save changes

Http-Method will be “PATCH” when updating with SaveChangesOptions.None. This step will send the updated top level properties.

dataServiceContext.SaveChanges();

or

dataServiceContext.SaveChanges(SaveChangesOptions.None);

Sample Code

Here I will provide several samples with their payloads.

1. Update top-level primitive property. Only the updated primitive property will be sent.

Sample Code:

public static void UpdatePrimitiveProperty()
{
DemoService dataServiceContext = new DemoService(new Uri("http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/"));
DataServiceCollection<Product> products = new DataServiceCollection<Product>(dataServiceContext.Products.Where(p=>p.ID == 0));
// Update primitive type under entity
products[0].Price = 3.0;
dataServiceContext.SaveChanges();
}

Payload:

{
"@odata.type":"#ODataDemo.Product",
"Price":3.0
}

 

2. Update property in top-level complex property. The entire complex property (“Address” in the example) instead of the updated property (“City” in the example) in the complex property will be sent to server.

Sample Code:

public static void UpdateComplexProperty()
{
DemoService dataServiceContext = new DemoService(new Uri("http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/"));
DataServiceCollection<Supplier> suppliers = new DataServiceCollection<Supplier>(dataServiceContext.Suppliers.Where(p => p.ID == 0));
// Update the property under complex type.
suppliers[0].Address.City = "Redmond";
dataServiceContext.SaveChanges();
}

Payload for complex type:

 

{
"@odata.type":"#ODataDemo.Supplier",
"Address":
{
"@odata.type":"#ODataDemo.Address",
"City":"Redmond",
"Country":"USA",
"State":"WA",
"Street":"NE 228th",
"ZipCode":"98074"
}
}

3. Update a navigation entity, only the updated property of the entity will be sent out.

Sample code:

public static void UpdateNavigationProperty()
{
DemoService dataServiceContext = new DemoService(new Uri("http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/"));
DataServiceCollection<Product> products = new DataServiceCollection<Product>(dataServiceContext.Products.Expand(p=>p.Supplier).Where(p=>p.ID == 0));
// Update Navigation
products[0].Supplier.Name = "White";
dataServiceContext.SaveChanges();
}

Payload:

{
"@odata.type":"#ODataDemo.Supplier",
"Name":"White"
}

Note

If you don’t use DataServiceCollection, then client will not support property tracking. For example:

public static void UpdatePrimitiveProperty2()
{
DemoService dataServiceContext = new DemoService(new Uri("http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/"));
var products = dataServiceContext.Products.Where(p => p.ID == 0).ToList();
// Update primitive type under entity
products[0].Price = 3.0;
dataServiceContext.SaveChanges();
}

Although client tracked the entity after ToList() was called. SaveChanges() will not send any request. The client cannot track the property change.

public static void UpdatePrimitiveProperty2()
{
DemoService dataServiceContext = new DemoService(new Uri("http://services.odata.org/V4/(S(readwrite))/OData/OData.svc/"));
var people = dataServiceContext.People.Where(p => p.PersonID == 1).ToList();
// Update primitive type under entity
people[0].LastName = "White";
dataServiceContext.UpdateObject(people[0]);
dataServiceContext.SaveChanges();
}

If you tried to use following code to update the entity, then the whole entity will be sent, instead of the only updated properties.

Payload will be like

{
"@odata.type":"#ODataDemo.Product",
"Description":"Whole grain bread",
"DiscontinuedDate":null,
"ID":0,
"Name":"Bread",
"Price":3.0,
"Rating":4,
"ReleaseDate":"1992-01-01T00:00:00Z"
}

Category
OData

Author

0 comments

Discussion is closed.