Working with CDS View

Objectives
After completing this lesson, you will be able to:

After completing this lesson, you will be able to:

  • Analyze a CDS view definition
  • Read data using a CDS view

Analyze CDS View

View Definitions in ABAP Core Data Services (ABAP CDS)

ABAP Code Data Services, or ABAP CDS for short, is an infrastructure for defining and consuming semantically rich data models in ABAP. They use a CDS DDL to define CDS entities that implement a semantic data model. The most important CDS modeling entities are CDS View entities.

The CDS View definition contains re-usable SQL logic; sometimes as simple as a projection of table fields and sometimes more sophisticated with calculations, aggregations, joins, unions, and so on.

A CDS View definition can contain associations to reflect the relations of the data model. Consumers of the view can use the associations to retrieve related data.

Finally, annotations are used to semantically enrich the view definition. This metadata is evaluated by frameworks that build on top of CDS View definitions. One such framework is the ABAP RESTful Application programming model (ABAP RAP), for which we will discuss an example later in this course.

Let's watch examples of CDS view definitions.

You already learned how to use the Data Preview tool to display and analyze the content of a database table. This tool is also available for CDS view entities.

To open the Data Preview for a given CDS entity, right-click anywhere in the data definition and choose Open With > Data Preview. Alternatively, place the cursor anywhere in the database table definition and press Ctrl + F8.

The tool displays the data returned by the CDS entity. The same functions are available to sort or filter the data and adjust the display.

If the view definition contains one or more associations, you can use them to display related data. To do so, proceed in the following manner:

  1. Right-click on a row in the display.
  2. From the context menu, choose Follow Association.
  3. From the list of available associations, choose the one in which you are interested.

If you want to find all CDS Views with a certain database table as a source, you can utilize the Where-used List tool of ADT. To use this tool, proceed as follows:

  1. Open the definition of the database table.
  2. Right-click anywhere in the source code and choose Get Where-used List from the context menu. Alternatively, you can press Ctrl + Shift + G, or choose the button from the toolbar with the same symbol.
  3. The Search view displays a list of all development objects that directly use the database table.

You can apply filters to the Where-used List if, for example, you are only interested in objects from certain packages or objects of the specific object type. The example illustrates how to filter for CDS views that use the table.

How to Analyze a CDS View

Reading Data Using a CDS View

When you implement a SELECT statement in ABAP, you can use a CDS view entity as the data source instead of reading from the database table directly. This has several advantages.

  • Re-use of the SQL logic contained in the CDS view
  • Concise, easy-to-read reading of related data using the associations
  • Sometimes the names of views and view elements are better readable than the more technical names of database tables and table fields

The SELECT statement in the example uses CDS view entity /DMO/I_Connection as a data source.

Note
Note that the names used in the FIELDS clause and WHERE conditions are the alias names of the view elements.

The third element in the FIELDS clause makes use of exposed association _Airline. It reads element name from the associated CDS view entity /DMO/I_Airline. This kind of element is called a path expression. The backslash (\) is a mandatory prefix for association names.

Analyze and Use a CDS View Entity

Task 1: Preparation

Steps

  1. If you finished the previous exercise Use Private Attributes and Constructors, create a copy of your global class ZCL_##_CONSTRUCTORS, and name the copy ZCL_##_CDS, where ## is your group number. Then skip the rest of this task.

    1. In the Project Explorer view on the left, expand your package.

    2. Expand node Source Code LibraryClasses

    3. Right-click the name of the class you want to copy and choose Duplicate.

    4. In the Name field, enter the name ZCL_##_CDS, where ## is your group number.

    5. Choose Next.

    6. Select your transport request and choose Finish.

  2. If you did not finish the previous exercise, create a new global class ZCL_##_CDS, where ## is your group number. Ensure that the class implements the interface IF_OO_ADT_CLASSRUN.

    1. Choose FileNewABAP Class.

    2. Enter the name of your package in the Package field. In the Name field, enter the name ZCL_##_CDS, where ## is your group number. Enter a description.

    3. In the Interfaces group box, choose Add.

    4. Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it to add it to the class definition.

    5. Choose Next.

    6. Select your transport request and choose Finish.

  3. Copy the following code between METHOD if_oo_adt_classrun~main. and ENDMETHOD. on the Global Class tab:

    Code snippet
    
    DATA connection TYPE REF TO lcl_connection.
        DATA connections TYPE TABLE OF REF TO lcl_connection.
    
    * First Instance
    **********************************************************************
    
        TRY.
            connection = NEW #(
                                i_carrier_id    = 'LH'
                                i_connection_id = '0400'
                              ).
    
            APPEND connection TO connections.
    
          CATCH cx_abap_invalid_value.
            out->write( `Method call failed` ).
        ENDTRY.
    
    * Second instance
    **********************************************************************
    
        TRY.
            connection = NEW #(
                                i_carrier_id    = 'AA'
                                i_connection_id = '0017'
                              ).
    
            APPEND connection TO connections.
    
          CATCH cx_abap_invalid_value.
            out->write( `Method call failed` ).
        ENDTRY.
    
    * Third instance
    **********************************************************************
    
        TRY.
            connection = NEW #(
                                i_carrier_id    = 'SQ'
                                i_connection_id = '0001'
                              ).
    
            APPEND connection TO connections.
    
          CATCH cx_abap_invalid_value.
            out->write( `Method call failed` ).
        ENDTRY.
    
    * Output
    **********************************************************************
    
        LOOP AT connections INTO connection.
    
          out->write( connection->get_output( ) ).
    
        ENDLOOP.
    
    Copy code
    1. Navigate to the Global Class tab and insert the source code between METHOD if_oo_adt_classrun~main. and ENDMETHOD..

  4. Copy the following code to the Local Types tab:

    Code snippet
    
    CLASS lcl_connection DEFINITION.
    
      PUBLIC SECTION.
    
        CLASS-DATA conn_counter TYPE i.
    
        METHODS constructor
          IMPORTING
            i_connection_id TYPE /dmo/connection_id
            i_carrier_id    TYPE /dmo/carrier_id
          RAISING
            cx_ABAP_INVALID_VALUE .
    
        METHODS get_output
          RETURNING
            VALUE(r_output) TYPE string_table.
    
      PROTECTED SECTION.
      PRIVATE SECTION.
        DATA carrier_id    TYPE /dmo/carrier_id.
        DATA connection_id TYPE /dmo/connection_id.
    
    ENDCLASS.
    
    CLASS lcl_connection IMPLEMENTATION.
    
      METHOD constructor.
        IF carrier_id IS INITIAL OR connection_id IS INITIAL.
          RAISE EXCEPTION TYPE cx_abap_invalid_value.
        ENDIF.
    
        me->connection_id = i_connection_id.
        me->carrier_id = i_carrier_id.
    
        conn_counter = conn_counter + 1.
    
      ENDMETHOD.
    
      METHOD get_output.
    
        APPEND |------------------------------| TO r_output.
        APPEND |Carrier:     { carrier_id    }| TO r_output.
        APPEND |Connection:  { connection_id }| TO r_output.
    
    
      ENDMETHOD.
    
    ENDCLASS.
    
    Copy code
    1. Navigate to the Local Types tab and insert the source code.

Task 2: Declare Additional Attributes

Extend local class lcl_connection with private instance attributes airport_from_id, airport_to_id, and carrier_name. Add some output for the new attributes to the implementation of method get_output( ).

Note
The new attributes are not filled, yet. In order to fill them we will add a SELECT statement to the constructor( ) in one of the next tasks of this exercise.

Steps

  1. Switch to the local class lcl_connection.

    1. In the global class, choose Local Types.

  2. Add the following private attributes to the class definition:

    Attributes

    Attribute NameScopeData Type
    airport_from_idinstance/DMO/AIRPORT_FROM_ID
    airport_to_idinstance/DMO/AIRPORT_TO_ID
    carrier_nameinstance/DMO/CARRIER_NAME
    1. After line PRIVATE SECTION. and before line ENDCLASS., add the following three statements:

      Code snippet
      
          DATA airport_from_id TYPE /dmo/airport_from_id.
          DATA airport_to_id   TYPE /dmo/airport_to_id.
      
          DATA carrier_name    TYPE /dmo/carrier_name.
      
      Copy code
  3. Extend the implementation of method get_output( ). Append more string templates to returning parameter r_output. Embed the new attributes as expressions into the string templates.

    1. Navigate to the implementation of method get_output( ).

    2. At the end of the method, add the following two statements:

      Code snippet
      
         APPEND |Departure:   { airport_from_id }|   TO r_output.
         APPEND |Destination: { airport_to_id   }|   TO r_output.
      
      Copy code
    3. Replace statement APPEND |Carrier:     { carrier_id      }| TO r_output. with the following statement:

      Code snippet
      
        APPEND |Carrier:     { carrier_id } { carrier_name }| TO r_output.
      
      Copy code
  4. Activate the class. Execute it and analyze the console output.

    1. Press Ctrl + F3 to activate the class.

    2. Press F9 to run the class.

Task 3: Analyze CDS View Entity

Analyze the definition of CDS View Entity /DMO/I_Connection.

Steps

  1. Open the development object that contains the definition of CDS View Entity /DMO/I_Connection.

    1. From the toolbar of ADT, choose Open ABAP Development Object or press Ctrl + Shift + A.

    2. In the input field, enter /DMO/I_Con as search string.

    3. In the list of matching items, click on /DMO/I_CONNECTION (Data Definition) and choose OK.

  2. Open the Tooltip Description for the data source of the CDS View entity. Find out the names of the fields that are typed with /dmo/airport_from_id and /dmo/airport_to_id.

    1. Click on /dmo/connection after keyword FROM and press F2 to show the tooltip description.

    2. The names of the fields are airport_from_id and airport_to_id.

  3. Analyze the element list of the CDS view entity. Find out the alias names for fields airport_from_id and airport_to_id.

    1. Navigate to the comma-seperated list between the pair of curly brackets ( { } ).

    2. The alias names are DepartureAirport and DestinationAirport.

  4. Open the Tooltip Description for the target of association _Airline. Find out the alias name of the field that is typed with /dmo/carrier_id.

    1. Click on /DMO/I_Carrier after association [1..1] to and press F2 to show the tooltip description.

    2. Field Name is typed with /dmo/carrier_name.

Task 4: Use CDS View Entity

In method constructor( ) of local class lcl_connection, implement a SELECT statements that reads values for the new attributes from CDS view entity /DMO/I_Connection.

Steps

  1. Return to local class lcl_connection in your global class ZCL_##_CDS.

    1. In the editor view of Eclipse, open tab ZCL_##_CDS.

    2. In the global class, choose Local Types.

  2. Navigate to the implementation of method constructor( ).

    1. Search for code line METHOD constructor..

  3. After statement ENDIF. add a SELECT statement that reads a single record from CDS view entity /DMO/I_Connection.

    1. After ENDIF., add the following code:

      Code snippet
      SELECT SINGLE
                     FROM /DMO/I_Connection
      Copy code
  4. Implement the FIELDS clause. Read view elements DepartureAirport and DestinationAirport. Also read view element Name from the target of association _Airline.

    Hint
    Use auto-completion (Ctrl + Space) to enter the names.
    1. After FROM /DMO/I_Connection enter FIELDS.

    2. After a blank, press Ctrl + Space and choose DepartureAirport.

    3. After a comma and a blank press Ctrl + Space again and choose DestinationAirport.

    4. After a comma and a blank, type in a backslash (\) , press Ctrl + Space and choose _Airline.

    5. Immediately after _Airline, type in a dash sign (-) , press Ctrl + Space and choose Name.

    6. The complete FIELDS clause should look like this:

      Code snippet
      
            FIELDS DepartureAirport, DestinationAirport, \_Airline-Name
      
      Copy code
  5. Implement the WHERE clause. Restrict the key elements of CDS view entity with the values of importing parameters i_carrier_id and i_connection_id. Do not forget to escape the parameters with prefix @.

    Hint
    Use auto-completion (Ctrl + Space) to enter the element names and parameter names.
    1. Add the following code after the FIELDS clause:

      Code snippet
      
           WHERE AirlineID    = @i_carrier_id
             AND ConnectionID = @i_connection_id
      
      Copy code
  6. Implement the INTO clause. Store the SELECT result in attributes airport_from_id, airport_to_id, and airline_name. Do not forget to escape the attributes with prefix @.

    Hint
    Use auto-completion (Ctrl + Space) to enter the attribute names.
    1. Add the following code after the WHERE clause:

      Code snippet
      
          INTO ( @airport_from_id, @airport_to_id, @carrier_name ).
      
      Copy code
    2. The complete SELECT statement should look like this:

      Code snippet
      
      SELECT SINGLE
            FROM /DMO/I_Connection
          FIELDS DepartureAirport, DestinationAirport, \_Airline-Name
           WHERE AirlineID    = @i_carrier_id
             AND ConnectionID = @i_connection_id
            INTO ( @airport_from_id, @airport_to_id, @carrier_name  ).
      
      Copy code
  7. Implement error handling after the SELECT statement. Check the content of system field sy-subrc. If it does not equal Zero, raise exception CX_ABAP_INVALID_VALUE.

    1. Add the following code after the SELECT statement:

      Code snippet
      
         IF sy-subrc <> 0.
            RAISE EXCEPTION TYPE cx_abap_invalid_value.
         ENDIF.
      
      Copy code
  8. Activate the class. Execute it and analyze the console output. Check that the output for the new attributes displays data.

    1. Press Ctrl + F3 to activate the class.

    2. Press F9 to run the class.

Log in to track your progress & complete quizzes