cancel
Showing results for 
Search instead for 
Did you mean: 

Equivalent for XSOdata's key generate local attribute in Cloud Application Programming Model

0 Kudos
406

Hi Experts,

We are currently migrating XS Classic oData services to Cloud Application Programming Model based services.In our previous application we had a XSOdata exposing a parametrized view which is using "key generate local " attribute to create a dynamic ID field.

When we Migrate to Cloud Application Programming Model do we have any equivalent attributes for entity or annotation aggregation to achieve the same result that we can using "key generate local "

Accepted Solutions (1)

Accepted Solutions (1)

hjb
Product and Topic Expert
Product and Topic Expert

The decisive sentence in the HANA docs is the very last one:

"As a consequence of the transient nature of generated local keys, it is not possible to define navigation properties on these entities or use them in filter or order by conditions."

With this modelling the generated key could be simulated:

entity E { i: Integer; };
service S {
view V as select from E { key null as k: Integer, i };
}

Translates into this API:

<EntityType Name="V">
<Key>
<PropertyRef Name="k"/>
</Key>
<Property Name="k" Type="Edm.Int32" Nullable="false"/>
<Property Name="i" Type="Edm.Int32"/>
</EntityType>
<Annotations Target="S.V/k">
<Annotation Term="Core.Computed" Bool="true"/>
</Annotations>

Core.Computed indicates that the key is generated and is to be ignored on a POST.
Of course the value for k must be calculated by a custom handler on each request.

It would even be possible to establish a navigation but as the key changes on every request, the modelling is questionable:

entity E { i: Integer; };
service S {
view V as select from E { key null as k: Integer, i }; entity X { key id: Integer; toV: association to V; }; }

Translates into OData:


      <EntityType Name="X">
        <Key>
          <PropertyRef Name="id"/>
        </Key>
        <Property Name="id" Type="Edm.Int32" Nullable="false"/>
        <NavigationProperty Name="toV" Type="S.V">
          <ReferentialConstraint Property="toV_k" ReferencedProperty="k"/>
        </NavigationProperty>
        <Property Name="toV_k" Type="Edm.Int32"/>
      </EntityType>

And to HANA SQL:

CREATE VIEW S_V AS SELECT
  NULL AS k,
  E_0.i
FROM E AS E_0;


CREATE TABLE S_X (
id INTEGER NOT NULL,
toV_k INTEGER,
PRIMARY KEY(id)
)
WITH ASSOCIATIONS (MANY TO ONE JOIN S_V AS toV ON (toV.k = toV_k));
0 Kudos

Hi,

hans-joachim.both we tried "key generation simulation" as per your previous comment. When we tried the same as below

define view md_supported_country_view(P_LANG : String(2)) as
    select from MD_Supported_Countries {
        key null as main: Integer,
        ID             as md_supported_country_ID,  
        iso_code       as md_supported_country_ISO_Code,
        is_inbound     as md_supported_country_Is_Inbound,
        is_outbound    as md_supported_country_Is_Outbound,
        texts.value    as md_supported_country_text
    }
    where
            texts.lang =  : P_LANG
        and ID            <> 0
        and current       =  'X';<img alt="" style="font-size: 15px; color: rgb(51, 51, 51);">
service caseManager {
entity SCVParams(P_LANG : String(2)) as select from CBTViews.md_supported_country_view(P_LANG: :P_LANG) {*} }

We are receiving error when we hit the exposed View entity in the url as below

Kindly suggest if we are doing it in the right manner

Thanks

Sahasranaman

Answers (5)

Answers (5)

hjb
Product and Topic Expert
Product and Topic Expert
0 Kudos

Did you check that view caseManager_SVParams in the DB has a column 'main'?

0 Kudos

hans-joachim.both Yes you were right It was our bad we failed build and run properly. It is working perfectly fine. Thanks for the inputs and time for helping us on the issue .

david.kunz2 Thanks for your time and suggestions as well

hjb
Product and Topic Expert
Product and Topic Expert
0 Kudos

david.kunz2 can you help here? I can't comment on runtime/query issues.

A modified version of your sample looks like this:

entity MD_Supported_Countries {
        ID: Integer;
        iso_code: Integer;
        is_inbound: Integer;
        is_outbound: Integer;
        value: Integer;
};
entity md_supported_country_view(P_LANG : String(2)) as
    select from MD_Supported_Countries {
        key null as main: Integer,
        ID             as md_supported_country_ID,  
        iso_code       as md_supported_country_ISO_Code,
        is_inbound     as md_supported_country_Is_Inbound,
        is_outbound    as md_supported_country_Is_Outbound,
        value    as md_supported_country_text
    };


service caseManager {
entity SCVParams(P_LANG : String(2)) as select from 
  md_supported_country_view(P_LANG: :P_LANG) {*} ;
}

And translates into this API:

      <EntityType Name="SCVParamsParameters">
        <Key>
          <PropertyRef Name="P_LANG"/>
        </Key>
        <Property Name="P_LANG" Type="Edm.String" MaxLength="2" Nullable="false"/>
        <NavigationProperty Name="Set" Type="Collection(caseManager.SCVParamsType)" Partner="Parameters" ContainsTarget="true"/>
      </EntityType>
      <EntityType Name="SCVParamsType">
        <Key>
          <PropertyRef Name="main"/>
        </Key>
        <Property Name="main" Type="Edm.Int32" Nullable="false"/>
        <Property Name="md_supported_country_ID" Type="Edm.Int32"/>
        <Property Name="md_supported_country_ISO_Code" Type="Edm.Int32"/>
        <Property Name="md_supported_country_Is_Inbound" Type="Edm.Int32"/>
        <Property Name="md_supported_country_Is_Outbound" Type="Edm.Int32"/>
        <Property Name="md_supported_country_text" Type="Edm.Int32"/>
        <NavigationProperty Name="Parameters" Type="caseManager.SCVParamsParameters" Partner="Set"/>
      </EntityType>
      <Annotations Target="caseManager.SCVParamsType/main">
        <Annotation Term="Core.Computed" Bool="true"/>
      </Annotations>

As well as this HANA SQL

CREATE TABLE MD_Supported_Countries (
  ID INTEGER,
  iso_code INTEGER,
  is_inbound INTEGER,
  is_outbound INTEGER,
  value INTEGER
);

CREATE VIEW caseManager_SCVParams(IN P_LANG NVARCHAR(2)) AS SELECT
  md_supported_country_view_0.main,
  md_supported_country_view_0.md_supported_country_ID,
  md_supported_country_view_0.md_supported_country_ISO_Code,
  md_supported_country_view_0.md_supported_country_Is_Inbound,
  md_supported_country_view_0.md_supported_country_Is_Outbound,
  md_supported_country_view_0.md_supported_country_text
FROM md_supported_country_view(P_LANG => :P_LANG) AS md_supported_country_view_0;

CREATE VIEW md_supported_country_view(IN P_LANG NVARCHAR(2)) AS SELECT
  NULL AS main,
  MD_Supported_Countries_0.ID AS md_supported_country_ID,
  MD_Supported_Countries_0.iso_code AS md_supported_country_ISO_Code,
  MD_Supported_Countries_0.is_inbound AS md_supported_country_Is_Inbound,
  MD_Supported_Countries_0.is_outbound AS md_supported_country_Is_Outbound,
  MD_Supported_Countries_0.value AS md_supported_country_text
FROM MD_Supported_Countries AS MD_Supported_Countries_0;
0 Kudos

Yes the modified version seems to be fine hans-joachim.both

david.kunz2 Kindly provide your suggestion for our issue

StevenDeSaeger
Contributor
0 Kudos

Hi,

I had the same kind of problem with the V2 proxy dumping on me ( for me because of the lack of a key field - as I wanted to use a different field then the entity GUID field as key in the actual ODATA service and did exclude the original key ).

So instead of selecting all fields in the entity definition - {*} - can you try writing out the fields you want indicate which one should be the key

entity .... as select from CBTViews(...) {
key md_supported_country_ID, 
<other fields you want to add>
} 

So the trick here being that you define the key yourself.

Not sure it works for your particular case but it did with mine.

Steven

OliverKlemenz
Product and Topic Expert
Product and Topic Expert
0 Kudos

Make sure, that you use corresponding CDS along the CDS OData V2 Adapter Proxy… So 1.5.1 should be used together with at least CDS 4.4.7… (same release date) then „keys“ function shall be available… could be that an earlier CDS 4 Version works as well… but CDS 3 will not work…

Hi steven.desaeger ,

We also tried the solution you suggested yes it works,but in our case there are some view where the fields from the already available artifacts cannot be taken as "key".Hence we are looking for a Dynamic key which can be added just like how "keys generator local" in XSC's XSOdata works .But otherwise the solution you mentioned is the ideal way.

Thanks

Sahasranaman

hjb
Product and Topic Expert
Product and Topic Expert
0 Kudos

This is a pretty good explanation of what a 'generated local key' is: https://answers.sap.com/answers/337785/view.html

and https://help.sap.com/viewer/b3d0daf2a98e49ada00bf31b7ca7a42e/2.0.02/en-US/e86a01a7699a46528624d44678...

david.kunz2 is correct there is no corresponding CAP feature.

0 Kudos

In response to David Comment

Hi david.kunz2 Sorry for adding in comments session as somehow Im not able to reply for your message.

But as per the thread you have mentioned https://answers.sap.com/questions/784739/sap-cloud-application-programming-model--generate-.html ?

We tried the below

and we got the ID__ key in the service with V2 Proxy adapter version 1.5.1.

The sole purpose we had to use this dynamic key generator was we were facing an error while exposing Parameterized view as mentioned above without a "key" in all the "@sap/cds-odata-v2-adapter-proxy" adapter whose version is higher than 1.4.30 hence we had to create a dynamic key at cds service level without disturbing the available artifacts.But still we encounter the below error as still it is not recognizing "ID__"as

    [cds] - GET /case-manager/SCVParams(P_LANG='EN')/Set
#2.0#2021 04 29 12:53:00:793#+00:00#ERROR#/cov2ap/Response#####daa00837-1ddd-4383-bfe5-361bbcc7ac5e##########daa00837-1ddd-4383-bfe5-361bbcc7ac5e#PLAIN##Cannot convert undefined or null to object#
Apr 29, 2021 12:53:00 PM Logger.js [daa00837-1ddd-4383-bfe5-361bbcc7ac5e] ERROR: Cannot convert undefined or null to object
TypeError: Cannot convert undefined or null to object
    at Function.keys (<anonymous>)
    at entityKey (/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js:2547:32)
    at entityUri (/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js:2543:25)
    at convertLocation (/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js:1878:22)
    at convertHeaders (/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js:1871:7)
    at convertProxyResponse (/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js:1721:11)
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

We have also observer that in the "/home/user/projects/v2proxycap/node_modules/@sap/cds-odata-v2-adapter-proxy/lib/index.js" of "@sap/cds-odata-v2-adapter-proxy" with version greater than 1.4.30 the below method is working based on entity key where it is throwing error as it is not able to recognize the key whereas in the 1.4.30 is is working based on "entity.elements"

Kindly suggest a better way to overcome the issue of dynamic keys so that it is recognised by the V2 adapter

david_kunz2
Product and Topic Expert
Product and Topic Expert

Hi sahasranaman1990,

Sorry, I was too eager to reply to your post, but I deleted it because the other question was a bit misleading.

As far as I know there is no corresponding feature in CAP, but I forwarded this question to my compiler colleagues, maybe they know more.
Best regards,
David