SAPUI5 OData - How to create new entry with association to existing entity?

Kennedy Kolmes picture Kennedy Kolmes · Mar 9, 2017 · Viewed 7.8k times · Source

I am currently using SAPUI5/OpenUI5 to consume and modify OData Services.

I want to create a new product entry over an HTTP POST Request and have problems to properly config the associations to a category. For developing reasons I am using a reference OData Service with this metadata. The Product already has the NavigationProperty to the right Category EntrySet.

<NavigationProperty Name="Category" Relationship="ODataDemo.Product_Category_Category_Products" FromRole="Product_Category" ToRole="Category_Products"/>

I am using the following JavaScript code in my controller:

var oCategory = oModel.getData("/Categories(0)");
var oEntry = {};
oEntry.ID = "10";
oEntry.Name = "Beer";
oEntry.Category = oCategory;

oModel.create("/Products", oEntry, {
    method: "POST",
    success: function(data) {...},
    error: function(response) {...}
});

The product is successfully created /Products(10) but the relation to the existing category /Products(10)/Category is not working properly. Instead a new category with the same ID and information is created (is this meant with 'deep insert'?) but I want to use the elected category (of course).

Do I have to reference the category differently or can I create the associations manually somehow? Shouldn't the OData Service check if the category ID already exists and then use the existing entry?

Is there any best practices for such cases?

Answer

Serban Petrescu picture Serban Petrescu · Mar 9, 2017

It's important to note that you are using an OData V2 service. Yes, by building the request the way you are doing it, you are actually doing a deep insert.

If you think about it, it makes sense, because you would not need to send the whole category information to just link the new product to the exiting category. What if you would change something in the category data? Should a deep insert result in an update?

In any case, OData v2 has something called "links" (see the OData terminology - www.odata.org). Basically each "association" between entities is represented through such a link. You can manage these links separately from the entity (e.g. you can remove and create links between existing entities; without having to change the entity itself - see the OData v2 operations, chapters 2.9 to 2.12).

Depending on the data format that you are using (by default, JSON if you are using sap.ui.model.odata.v2.ODataModel), you can create entity links in the same time when creating new entities. Check out this answer: https://stackoverflow.com/a/4695387/7612556.

In a nutshell, you would have to write something along the lines of:

oModel.create("/Products", {
    ID: "10",
    Name: "Beer",
    Category: {__metadata: {uri: "/Categories(0)"}}
}, {
    method: "POST",
    success: function(data) {...},
    error: function(response) {...}
});