Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
miltonc
Product and Topic Expert
Product and Topic Expert

Creating hierarchical data using Content-ID Referencing in a Change Set (Batch Request)

In the previous blog on deep inserts, I had mentioned that there is a limitation in OData specifications that does not allow deep inserts 1:N for Offline applications.  I also talked about a workaround that allows us to persist property values of the parent and child entities in the datavault when the device is offline.  Later when the device is online, we can perform a deep insert 1:N followed by a refresh of the Offline Store.

There is yet another alternative to creating hierarchical data.  This can be accomplished using Content-ID referencing in a change set (batch request).  Please refer to the OData specifications on Referencing Requests in a Change Set.

In our example, we will use the universally available OData Service found in http://services.odata.org.  Since this involves updating the backend data, use the link to create a full access (Read-Write) service.

Difference between deep insert and Content-ID referencing in a change set (batch request) ?

There are quite a few similarities between deep insert and Content-ID referencing in a change set (batch request).  Both these approaches can be used to insert hierarchical data.  The table below describes some of the differences between deep insert and Content-ID referencing in a change set (batch request).

Deep Insert

Content-ID referencing in a change set (batch request)


Deep insert allows creating hierarchical data using a single payload in a single request

Multiple requests are grouped into a single request

Deep Insert is somewhat easier. The single payload in the POST request is in the same format as that of a GET request with $expand

If a MIME part representing an Insert request within a ChangeSet includes a Content-ID header, then the new entity represented by that part may be referenced by subsequent requests within the same ChangeSet by referring to the Content-ID value prefixed with a “$” character.

Most OData providers support deep insert – including Integration Gateway

Integration Gateway does not support Content-ID referencing in a batch request.  However, there are other 3rd party OData producers that support Content-ID referencing in a change set.

Limitation in OData specification does not allow for deep inserts 1:N for Offline applications

No such limitation. Hierarchical data can be inserted in both Online and Offline applications

Creating hierarchical data with 1:N relationship using Content-ID referencing in a change set (batch request - Online)

As in the previous blog, the first step is to create the parent entity.  PropertyCreationMode.All indicates that you will be supplying all the values for the properties.  If you do not supply values for any of the optional properties, the default value will be used.  Note that you also want to call the AllocateNavigationProperties method to establish the navigation properties in the parent entity.  The following code snippet creates a local parent entity and sets the values for the properties.

var parentEntity = new SAP.Data.OData.Online.ODataEntity("ODataDemo.Category");

parentEntity.SetResourcePath("Categories", "Categories");

Store.AllocateProperties(parentEntity, PropertyCreationMode.All);

SharedContext.Context.OnlineStore.AllocateNavigationProperties(parentEntity);

parentEntity.Properties["ID"].Value = 3;

parentEntity.Properties["Name"].Value = "Home Goods";

The next step is to create the child entities.  The following code snippet creates 2 child entities and sets the values for the properties.

var childEntity1 = new SAP.Data.OData.Online.ODataEntity("ODataDemo.Product");

childEntity1.SetResourcePath("Products", "Products");

SharedContext.Context.OnlineStore.AllocateProperties(childEntity1, SAP.Data.OData.Store.PropertyCreationMode.All);

childEntity1.Properties["ID"].Value = 501;

childEntity1.Properties["Name"].Value = "Tennis racket";

childEntity1.Properties["Description"].Value = "Prince O-Shark Tennis racket";

childEntity1.Properties["ReleaseDate"].Value = DateTime.Now;

childEntity1.Properties["Rating"].Value = 5;

childEntity1.Properties["Price"].Value = 174.99m;

var childEntity2 = new SAP.Data.OData.Online.ODataEntity("ODataDemo.Product");

childEntity1.SetResourcePath("Products", "Products");

SharedContext.Context.OnlineStore.AllocateProperties(childEntity2, SAP.Data.OData.Store.PropertyCreationMode.All);

childEntity2.Properties["ID"].Value = 502;

childEntity2.Properties["Name"].Value = "Tennis shoes";

childEntity2.Properties["Description"].Value = "Prince Invisible Shoes";

childEntity2.Properties["ReleaseDate"].Value = DateTime.Now;

childEntity2.Properties["Rating"].Value = 5;

childEntity2.Properties["Price"].Value = 124.99m;

The next step is to group the requests into a single request.  This is done by creating a change set and adding the requests to the change set.  The request for the parent entity contains the Content-ID header.   Subsequent child requests in the same Change Set reference the Content-ID prefixed by the “$” character.  The following snippet of code builds the batch request with the Change Set containing insert requests for both the parent and the child entities.

var contentId = 1;

this.ChangeSet = new ODataRequestChangeSet();

this.BatchRequest = newODataRequestParametersBatch();

var parentItem = new ODataRequestParametersSingle("Categories", RequestMode.Create, parentEntity);

parentItem.ContentId = contentId.ToString();

this.ChangeSet.Add(parentItem);

this.ChangeSet.Add(new ODataRequestParametersSingle("$" + contentId + "/Products", RequestMode.Create, childEntity1));

this.ChangeSet.Add(newODataRequestParametersSingle("$" + contentId + "/Products", RequestMode.Create, childEntity2));

this.BatchRequest.Add(ChangeSet);

The last step is to submit the POST request.  The following snippet of code submits the POST request and also parses the response.

this.ResponseList = ((IReadOnlyCollection<IODataResponseBatchItem>)((IODataResponseBatch)((await SharedContext.Context.OnlineStore.ScheduleRequest(this.BatchRequest).Response))).Responses);

ParseResponse();

public void ParseResponse()

{

   foreach (var item in ResponseList)

   {

      if (item is IODataResponseChangeSet)

      {

         foreach (var element in ((ODataResponseChangeSet)item).Responses)

         {

            System.Diagnostics.Debug.WriteLine("Status Code: " + element.Headers["http.code"].ElementAt(0));

         }

   }

}

Creating hierarchical data with 1:N relationship using Content-ID referencing in a change set (batch request - Offline)

The steps involved in creating hierarchical data with 1:N relationship using Content-ID referencing in a change set (batch request) for an Offline application is identical to the steps outlined in the previous section for an Online application.  The only difference is that you will use the Offline Store instead of the Online Store.  You will also need to call Flush and Refresh later when the device becomes online.

The following code snippet submits the POST request for the Offline Store.

this.ResponseList = ((IReadOnlyCollection<IODataResponseBatchItem>)((IODataResponseBatch)((await SharedContext.Context.OfflineStore.ScheduleRequest(this.BatchRequest).Response))).Responses);

When the device is online, simply call the Flush and the Refresh method to submit local changes to the backend and to retrieve data from the backend.

await SharedContext.Context.OfflineStore.ScheduleFlushQueuedRequestsAsync();

await SharedContext.Context.OfflineStore.ScheduleRefreshAsync();

Please find attached the source code for a sample Windows application that creates hierarchical data using Content-ID referencing in a change set (batch request).

In the next blog, I will talk about cancelling asynchronous request in SAP Mobile Platform SDK.

4 Comments