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: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
5,891
Phew…
The previous tutorial was kind of dry material and exhausting reading….
Agreed, but in this tutorial we’ll skip those lengthy explanations, just show how it needs to be done.
To be done? What needs to be done?
Ah, you’re right, almost forgot the intro…

Intro


This blog is part of a series of tutorials for beginners, to get started with SAP Cloud Platform Backend service
With the Backend service, you can create an API without code, only with a data model, e.g. CDS model
In the previous tutorial we discussed how to define unmanaged one-to-one association
In the present tutorial, we’re going to learn how CDS (Core Data and Services) helps to define managed associations.
CDS helps?
Yes, I really mean it. It helps: it manages.
ehmmm, but mangers are not really known to be…
Sorry, just continue reading

Part I: managed one-to-one association


Please read the previous tutorial in order to see the difference between unmanaged and managed

The Model


For better comparison and easier understanding, I thought of reusing the model of previous tutorial, but modified such that we can leverage the power of CDS’s managed association
service ProductService {

// Managed 1:1 relation
entity CustomerEntity{
key customerID : Integer;
companyName : String;
// no foreign key here anymore
linkToContact : Association to ContactEntity; // no condition anymore
}

entity ContactEntity{
key contactID : Integer;
contactName : String;
contactPhone : String;
}
}

 

If you compare this model to the previous one, you’ll notice 2 differences:

The 2 differences:

  1. In CustomerEntity, we don’t need the foreign key property anymore (it was called contactProperty)

  2. The association doesn’t have an “on” condition anymore


Now let’s create an API based on this model (see here for instructions)
Afterwards, check the metadata of the generated OData service:
<EntityType Name="CustomerEntity">
<Key>
<PropertyRef Name="customerID" />
</Key>
<Property Name="customerID" Type="Edm.Int32" Nullable="false" />
<Property Name="companyName" Type="Edm.String" />
<Property Name="linkToContact_contactID" Type="Edm.Int32" />
<NavigationProperty Name="linkToContact" Type="ProductService.ContactEntity">
<ReferentialConstraint Property="linkToContact_contactID" ReferencedProperty="contactID" />
</NavigationProperty>
</EntityType>

Interesting to observe:

  1. In the OData EntityType “CustomerEntity” there’s a property which we didn’t define in the CDS-entity
    It is called linkToContact_contactID
    This has been magically added by CDS

  2. In the OData NavigationProperty, there’s a ReferentialConstraint which we didn’t define in the CDS association
    It defines a constraint on the key property of the target entity and the magic-property
    This has been magically added by CDS


See below for direct comparison:



 

Test it


Since we haven’t changed any property names, we can proceed same way like described in the previous tutorial.

The navigation should work in the same way like in the previous tutorial.

https://.../DEFAULT/PRODUCTSERVICE;v=3/CustomerEntity(1)/linkToContact

 

PART II : Managed one-to-many association


Now we’re going to have a look at a different example :
Managed one-to-many association and the corresponding backlink

The model


Let’s use the same scenario, with a little change
We assume that a customer/company can have multiple contact persons.
And that a contact person is responsible for one company only, as such we can navigate from a contact back to the company
service ProductService {

// managed association: 1 to many
entity CustomerEntity{
key customerID : Integer;
companyName : String;
linkToContacts : Association to many ContactEntity
on linkToContacts.linkToCustomer = $self;
}

// managed association: one to one
entity ContactEntity{
key contactID : Integer;
contactName : String;
linkToCustomer : Association to CustomerEntity;
}
}

 

The corresponding metadata of the OData service:
<EntityType Name="CustomerEntity">
<Key>
<PropertyRef Name="customerID" />
</Key>
<Property Name="customerID" Type="Edm.Int32"/>
<Property Name="companyName" Type="Edm.String" />
<NavigationProperty Name="linkToContacts" Type="Collection(ProductService.ContactEntity)" Partner="linkToCustomer" />
</EntityType>
<EntityType Name="ContactEntity">
<Key>
<PropertyRef Name="contactID" />
</Key>
<Property Name="contactID" Type="Edm.Int32"/>
<Property Name="contactName" Type="Edm.String" />
<Property Name="linkToCustomer_customerID" Type="Edm.Int32" />
<NavigationProperty Name="linkToCustomer" Type="ProductService.CustomerEntity" Partner="linkToContacts">
<ReferentialConstraint Property="linkToCustomer_customerID" ReferencedProperty="customerID" />
</NavigationProperty>
</EntityType>

One interesting detail could be the “Partner” attribute in the NavigationProperty tag. It makes clear that we have defined a bi-directional association.

Test


After creating the API, we create some sample data
In order to test the to-many association, we need to create several ContactEntity for one Customer

The result of navigating from a CustomerEntity to the contacts is a collection

https://.../DEFAULT/PRODUCTSERVICE;v=4/CustomerEntity(1)/linkToContacts



 

Summary


In this tutorial we’ve learned how to define managed associations in CDS
The previous tutorial covered the unmanaged association, along with detailed explanations

Links


Preparation and configuration for using SAP Cloud Platform Backend Service

Tools for modelling (typing) CDS

First tutorial:
https://blogs.sap.com/2019/01/25/sap-cloud-platform-backend-service-tutorial-1-easy-api-creation/com...

Previous tutorial:
https://blogs.sap.com/2019/02/20/sap-cloud-platform-backend-service-tutorial-3-cds-how-to-define-ass...

Next tutorial:
https://blogs.sap.com/2019/02/28/sap-cloud-platform-backend-service-tutorial-5-cds-using-property-fa...

The tutorial overview page

CDS docu on associations:
https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/9ead8e4701d04848a6fdc843567...

OData specification:
NavigationProperty section

Appendix: the data model


service ProductService {

// managed association: 1 to many
entity CustomerEntity{
key customerID : Integer;
companyName : String;
linkToContacts : Association to many ContactEntity
on linkToContacts.linkToCustomer = $self;
}

// managed association: one to one
entity ContactEntity{
key contactID : Integer;
contactName : String;
linkToCustomer : Association to CustomerEntity;
}
}
11 Comments
aman_khanna
Advisor
Advisor
0 Kudos
Many thanks for the great blog, carlos.roggan

Since I'm new to this lingo, please expand on what $self means?

Thanks.
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hello aman.khanna

The $self is a shortcut in CDS which once more aims to make the language concise and intuitive.I think it helps to look at the runtime example
I imagine I am a customer and want to find my contact persons. Well, my contacts are all those who have a customerID which is myself.
In the CDS model above, the contact entity doesn't have a property customerID. The reason is that it has a managed association "linkToCustomer" and as such, the (obvious) customerID is generated on the fly.
When looking at the runtime example, pasted above, then we can see that the OData service indeed DOES contain that generated CustomerID property. It is called "linkToCustomer_customerID":



We can see that all entries do point at the same customer, which is myself, so it makes sense to model it as "managed Association"
So, bottom line, I think CDS helps to avoid to add the foreign-key property "customerID", which would then end up in the where-clause something like ContactEntity.customerID equals CustomerEntity.customerID
And all that much more complicated in case of multiple composed key elements
Instead, we can just write the $self, which points at the entity which declares it

Kind Regards,

Carlos
former_member662946
Discoverer
0 Kudos
Very well written blog. Is there a way to hide the foreign key from the parent entity in the service while using a one to one association. In this case the field
linkToContact_contactID
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hi nicholdvs111 ,

Thanks so much for the feedback! 😉
Not sure if I understand your question correct.
If you use managed association, then the advantage is exactly that the foreign key is hidden, because CDS generates it on the fly under the hood
Only in the OData metadata doc it is visible, but this file is also generated and you don't work with it.
The foreign key cannot be completely removed, as it is required by the underlying database tables.

Does this answer your question?
Kind Regards,
Carlos
former_member662946
Discoverer
0 Kudos

Thanks Carlos, It does answer my question.

Is there any way to hide the primary key field from being exposed in the catalog service for associations? Is there any annotation or something?

Note: I am using SLT replicated tables in CDS.

Kind Regards,

Nichol

CarlosRoggan
Product and Topic Expert
Product and Topic Expert
Hi nicholdvs111 ,
I'm not sure if I get you correctly:

1. In CDS, if you have reusable data-model and e.g. multiple service-models:
In your service-model you use the data-model, but you can "hide" elements of your choice.
Like that, you can "customize" the model.
The keyword is "excluding"
See here: https://blogs.sap.com/2019/03/11/sap-cloud-platform-backend-service-tutorial-9-cds-how-to-use-select...

2. In ODATA:
OData is a protocol which has the advantage that the service is described by the metadata-document.
The metadata are e.g. used by UI technologies like UI5 or FE, which allows to generate UI-controls and controller-logic based on the metadata
As such: the metadata can NOT hide anything
Now, with the great functionality of CAP, to auto-generate and auto-expose an OData service on the fly, we can understand that the service-model-cds-file HAS to expose everything that is required in the OData-layer.
If you exclude properties or associations in service-cds, then it won't be there in the exposed OData-service.
I'm not sure if that is what you wish to do?

Kind Regards,

Carlos
BenedictV
Active Contributor
0 Kudos

Hi carlos.roggan ,

Thank you for this series of excellent tutorials. I enjoyed the previous tutorial on odata introduction.

I am not able to find the Backend Service as mentioned in https://blogs.sap.com/2019/01/25/sap-cloud-platform-backend-service-tutorial-0.1-preparation/#signup - How do I access it in the new BTP trial platform?

 

In the managed association example above an Association is defined in Part 1 above we define the association between  the two entities,

linkToContact :  Association to ContactEntity;

But how does the system know which field to use for establishing the Navigation from? how is this 'magically' established, especially if we have no Key or more than one Key. I am confused. Can you please elaborate?

 

CarlosRoggan
Product and Topic Expert
Product and Topic Expert
Hi vasanth.vf ,
as far as I understand, CAP and CDS try to cover the most typical use cases of developers of business applications.
So tries to establish conventions and defaults.
In fact, the line which you've quoted above, looks easy and human readable.
You're right, when trying to understand in details, we have to wonder about it.
That's why I added the comparisions and screenshots above.
In case of simple association like above, we can remove the property used for navigation, because the information is contained already in the association:
We want to navigate to contact, that's enough info.
Now, it is not enough for OData.
As such, CDS will generate the missing property, for which you've asked.
The prove is in some generated CSN files, which we cannot access in Backend Service.
But we can see it in the OData model.
This is why it is called "managed association", I guess.

Now you're asking for more complex cases like multiple key fields:
In such cases, probably CDS cannot make default assumptions and there is no "managed" and we have to declare everything manually, unmanaged.
I think that was described in the previous blog, via the "on" statement which probably can be extended with multiple properties.

Please forgive, I haven't been working on these topics since quite some years...

About accessing the backend service, I have to find out

Kind Regards,
And thank you for the nice feedback!
Carlos
BenedictV
Active Contributor
Thank you carlos.roggan for the explanation. Its more clearer now. I am planning to create a few services with associations and check my self.
ashutosh06
Member
0 Kudos
Hi Carlos,

Thanks for such a nice explanation!

I have one question regarding managed association.

In managed association framework implicitly adds foreign key element to entity CustomerEntity which is linkToContact_contactID in below example. Since these entities when deployed creates the DB table so eventually DB table will have one more field linkToContact_contactID.

So while inserting the records to the table CustomerEntity  how the values to this field will be inserted because from application user POV this field is of no use and I assume this field will not appear on the UI?
    // Managed 1:1 relation 
entity CustomerEntity{
key customerID : Integer;
companyName : String;
// no foreign key here anymore
linkToContact : Association to ContactEntity; // no condition anymore
}

entity ContactEntity{
key contactID : Integer;
contactName : String;
contactPhone : String;

 

Thanks,

Ashutosh
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
0 Kudos
Hello ashutosh06 ,

thank you so much for so nice feedback!
This Blog series is not being followed up anymore, so I'd ask you to kindly post your question in the community with appropriate tags for cap or cds at https://answers.sap.com/

Thanks,
Carlos