This is a test message to test the length of the message box.
Login
ABAP RAP Entity Manipulation Language
Erstellt von Software-Heroes

RAP - EML (Teil 2)

317

Komplexe RAP Entitäten mit der Entity Manipulation Language ansteuern, darum geht es in diesem Artikel und wie du mit tiefen Knoten arbeitest.

Werbung


Die Grundlagen für die Entity Manipulation Language, kurz EML, haben wir bereits vor einer Weile in einem ersten Artikel gelegt. Dort haben wir dir gezeigt, was EML ist und wie du es mit RAP Objekten einsetzen kannst. In diesem Artikel schauen wir uns das Gleiche bei komplexen Entitäten an.

 

Einleitung

Im Artikel letzte Woche haben wir gemeinsam ein komplexes Datenmodell aufgebaut und uns die Unterschiede zu einer einfachen Entität angeschaut. Dabei besteht das Modell nicht nur aus einer einzigen Tabelle, sondern mehrere Tabellen bilden ein Objekt ab, so wie es in der "normalen" Welt der Standard ist.

 

EML bildet die Grundlage zum Zugriff auf RAP Objekte, ohne über den OData Service zu gehen, sondern als schneller Weg im aktuellen System auf Funktionen des Objektes zuzugreifen. Die Funktionen sind innerhalb eines Objekts stark gekapselt und damit leicht wartbar und wiederverwendbar. 

Bei der Entwicklung der Statements unterstützt ebenso die IDE (Eclipse) und gibt passende Vorschläge beim Zugriff auf die Entitäten:

 

Lesen

Im ersten Schritt lesen wir mit einem EML Statement beide abhängige Entitäten, dazu definieren wir uns einen Filter, dieser kann später von außen kommen oder auf anderen Wege aufgebaut werden. Dazu selektieren wir zwei Belege von der Datenbank, die Belegnummern können dabei zu deinen Belegen abweichen:

DATA lt_filter TYPE STANDARD TABLE OF ZBS_R_RAPCInvoice WITH EMPTY KEY.

lt_filter = VALUE #( ( Document = '30000000' )
                     ( Document = '30000005' ) ).

 

Nun bauen wir das entsprechende Lesestatement auf, zur besseren Lesbarkeit haben wir es einmal aufbereitet geschrieben, damit wir die einzelnen Schritte beschreiben können:

READ ENTITIES OF ZBS_R_RAPCInvoice

     ENTITY Invoice
     ALL FIELDS WITH CORRESPONDING #( lt_filter )
     RESULT DATA(lt_invoice)
     
     ENTITY Invoice BY \_Position
     FIELDS ( Document PositionNumber Material ) WITH CORRESPONDING #( lt_filter )
     RESULT DATA(lt_position)
     
     FAILED FINAL(ls_failed).

 

Zuerst einmal sprechen wir das RAP Objekt an, aus welchem wir die Informationen lesen wollen. Dann geben wir die erste Entität an, aus der wir die Daten lesen wollen. Das Schema entspricht dem Standard, nach der Entität kommt die Einschränkung der Felder, dann der Schlüssel und schließlich weisen wir das Ergebnis einer Variable zu. Im zweiten Abschnitt wiederholen wir dieses Verhalten, zur besseren Veranschaulichung haben wir dieses Mal die Felder eingegrenzt, um nicht alle Inhalte von der Datenbank zu lesen. Den Filter übergeben wir wieder und können das Ergebnis zuweisen. Zum Schluss übernehmen wir noch die fehlgeschlagenen Zugriffe. In der Struktur sind Informationen enthalten, wenn bestimmte Zugriffe nicht funktioniert haben.

Das Ergebnis aus den Tabellen sieht nun wie folgt aus:

 

Einfügen

Im zweiten Schritt wollen wir einmal neue Daten einfügen und in einem Schwung Rechnungen und die passenden Positionen anlegen. Dazu bereiten wir die Daten vor, die wir im nächsten Schritt einfügen wollen:

DATA lt_new_invoice  TYPE TABLE FOR CREATE ZBS_R_RAPCInvoice.
DATA lt_new_position TYPE TABLE FOR CREATE ZBS_R_RAPCInvoice\_Position.

lt_new_invoice = VALUE #( ( %cid     = 'B1'
                            Document = '40000000'
                            Partner  = '1000000004'
                            %control = VALUE #( Document = if_abap_behv=>mk-on Partner = if_abap_behv=>mk-on ) ) ).

lt_new_position = VALUE #(
    ( %cid_ref = 'B1'
      %target  = VALUE #(
          ( %cid           = 'P1'
            PositionNumber = 1
            Material       = 'R0001'
            %control       = VALUE #( PositionNumber = if_abap_behv=>mk-on Material = if_abap_behv=>mk-on ) )
          ( %cid           = 'P2'
            PositionNumber = 2
            Price          = '2.20'
            Currency       = 'EUR'
            %control       = VALUE #( PositionNumber = if_abap_behv=>mk-on Price = if_abap_behv=>mk-on Currency = if_abap_behv=>mk-on ) ) ) ) ).

 

Zu beachten beim Datenaufbau ist die Verwendung der richtigen Referenz (%CID), denn damit wir die Rechnung mit der Position verbunden. Unter %TARGET hängen wir dann unsere Daten an die Position dran. Die Positionen erhalten dazu eigene IDs. Wichtig beim Vorbereiten der Daten ist die Befüllung der %CONTROL Struktur, da nur dadurch die Felder beim Einfügen auch befüllt werden. Eine Besonderheit gibt es noch beim Erstellen der Datentypen für die Hauptentität und die passende abhängige Entität. Der Aufruf der Anlage sieht dann wieder wie folgt aus:

MODIFY ENTITIES OF ZBS_R_RAPCInvoice

       ENTITY Invoice
       CREATE FROM lt_new_invoice
       
       ENTITY Invoice
       CREATE BY \_Position FROM lt_new_position
       
       FAILED DATA(ls_failed).

COMMIT ENTITIES.

 

Aufruf des MODIFY um die ändernde Aktion einzuleiten. Dann wird die erste Entität mitgegeben (Rechnungen) und im nächsten Schritt die Positionen, hier aber darauf achten, dass die Anlage über die Assoziation stattfindet. Es ist ebenso möglich direkt Positionen anzulegen, dafür müssten aber die Schlüssel (Dokumentennummer) bekannt sein. Im letzten Schritt nehmen wir noch die Struktur entgegen, um auf Fehler reagieren zu können. Im Anschluss nicht vergessen einen COMMIT zu setzen, damit die Daten auf die Datenbank geschrieben werden.

Über den Data-Preview können wir uns die neuen Datensätze anschauen, hier einmal ein Auszug aus der Positionstabelle mit den beiden erstellten Positionen der Rechnung:

 

Löschen

Bevor wir den Datensatz löschen können, sollten wir zuerst einmal definieren, welche Schlüssel wir löschen wollen. Dazu verwenden wir wieder eine Dummy Tabelle als Filter der Datensätze.

DATA lt_filter TYPE STANDARD TABLE OF ZBS_R_RAPCInvoice WITH EMPTY KEY.

lt_filter = VALUE #( ( Document = '40000000' ) ).

 

Im nächsten Schritt geben wir die Schlüssel dem MODIFY mit. Hier reicht es über das Dokument zu löschen, es werden alle abhängigen Entitäten berücksichtigt und ebenfalls von der Datenbank gelöscht.

MODIFY ENTITIES OF ZBS_R_RAPCInvoice
       ENTITY Invoice
       DELETE FROM CORRESPONDING #( lt_filter )
       FAILED DATA(ls_failed).

COMMIT ENTITIES.

 

Das Statement zum Löschen ist sehr kurz und doch sehr praktisch. RAP kümmert sich um die abhängigen Entitäten die weiter unten kommen, sodass wir beim Löschen nicht darauf achten müssen.

 

Vollständiges Beispiel

Am Ende noch einmal das vollständige Beispiel der gezeigten Demos. Für die Formatierung verwenden wir den ABAP Cleaner, ein praktisches Werkzeug um Quellcode sauber zu halten:

CLASS zcl_bs_demo_crap_eml DEFINITION PUBLIC FINAL CREATE PUBLIC.
  PUBLIC SECTION.
    INTERFACES if_oo_adt_classrun.

  PRIVATE SECTION.
    METHODS read_data
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.

    METHODS insert_data
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.

    METHODS delete_data
      IMPORTING io_out TYPE REF TO if_oo_adt_classrun_out.

ENDCLASS.


CLASS zcl_bs_demo_crap_eml IMPLEMENTATION.
  METHOD if_oo_adt_classrun~main.
    read_data( out ).
    insert_data( out ).
    delete_data( out ).
  ENDMETHOD.


  METHOD read_data.
    DATA lt_filter TYPE STANDARD TABLE OF ZBS_R_RAPCInvoice WITH EMPTY KEY.

    lt_filter = VALUE #( ( Document = '30000000' )
                         ( Document = '30000005' ) ).

    READ ENTITIES OF ZBS_R_RAPCInvoice
         ENTITY Invoice
         ALL FIELDS WITH CORRESPONDING #( lt_filter )
         RESULT DATA(lt_invoice)
         ENTITY Invoice BY \_Position
         FIELDS ( Document PositionNumber Material ) WITH CORRESPONDING #( lt_filter )
         RESULT DATA(lt_position)
         FAILED FINAL(ls_failed).

    IF ls_failed-invoice IS NOT INITIAL.
      io_out->write( `Failed!` ).
    ENDIF.

    io_out->write( `Invoices:` ).
    io_out->write( lt_invoice ).
    io_out->write( `Positions:` ).
    io_out->write( lt_position ).
  ENDMETHOD.


  METHOD insert_data.
    DATA lt_new_invoice  TYPE TABLE FOR CREATE ZBS_R_RAPCInvoice.
    DATA lt_new_position TYPE TABLE FOR CREATE ZBS_R_RAPCInvoice\_Position.

    lt_new_invoice = VALUE #( ( %cid     = 'B1'
                                Document = '40000000'
                                Partner  = '1000000004'
                                %control = VALUE #( Document = if_abap_behv=>mk-on Partner = if_abap_behv=>mk-on ) ) ).

    lt_new_position = VALUE #(
        ( %cid_ref = 'B1'
          %target  = VALUE #(
              ( %cid           = 'P1'
                PositionNumber = 1
                Material       = 'R0001'
                %control       = VALUE #( PositionNumber = if_abap_behv=>mk-on Material = if_abap_behv=>mk-on ) )
              ( %cid           = 'P2'
                PositionNumber = 2
                Price          = '2.20'
                Currency       = 'EUR'
                %control       = VALUE #( PositionNumber = if_abap_behv=>mk-on Price = if_abap_behv=>mk-on Currency = if_abap_behv=>mk-on ) ) ) ) ).

    MODIFY ENTITIES OF ZBS_R_RAPCInvoice
           ENTITY Invoice
           CREATE FROM lt_new_invoice
           ENTITY Invoice
           CREATE BY \_Position FROM lt_new_position
           FAILED DATA(ls_failed).

    COMMIT ENTITIES.

    IF ls_failed-invoice IS NOT INITIAL.
      io_out->write( `Failed!` ).
    ELSE.
      io_out->write( `Creation OK` ).
    ENDIF.
  ENDMETHOD.


  METHOD delete_data.
    DATA lt_filter TYPE STANDARD TABLE OF ZBS_R_RAPCInvoice WITH EMPTY KEY.

    lt_filter = VALUE #( ( Document = '40000000' ) ).

    MODIFY ENTITIES OF ZBS_R_RAPCInvoice
           ENTITY Invoice
           DELETE FROM CORRESPONDING #( lt_filter )
           FAILED DATA(ls_failed).

    COMMIT ENTITIES.

    IF ls_failed-invoice IS NOT INITIAL.
      io_out->write( `Failed!` ).
    ELSE.
      io_out->write( `Deletion OK` ).
    ENDIF.
  ENDMETHOD.
ENDCLASS.

 

Fazit

Das Arbeiten mit EML sollte dir nach unserem Artikel einfacher fallen und auch bei komplexen und größeren RAP Objekten musst du keine Angst haben, diese nicht mehr handeln zu können. Es gibt einige Dinge zu beachten, wenn du mit mehreren Entitäten arbeitest.


Enthaltene Themen:
RAPBTPEML
Kommentare (0)



Und weiter ...

Bist du zufrieden mit dem Inhalt des Artikels? Wir posten jeden Freitag neuen Content im Bereich ABAP und unregelmäßig in allen anderen Bereichen. Schaue bei unseren Tools und Apps vorbei, diese stellen wir kostenlos zur Verfügung.


RAP - Mehrere Filter und Einstellungen

Kategorie - ABAP

Wie sieht es eigentlich aus, wenn wir in RAP mehrere Filter und Felder als Standard setzen wollen und dazu noch eine standardmäßige Sortierung benötigen?

16.05.2025

RAP - Länge von Meldungen

Kategorie - ABAP

Deine Meldung wird bei der Ausgabe mit RAP abgeschnitten? Lass uns das Problem und eine Lösung anschauen.

13.05.2025

RAP - Suchhilfe und Schlüssel optimieren

Kategorie - ABAP

In diesem Artikel optimieren wir unsere Suchhilfen im Custom Pattern, verwenden das Additional Binding und machen unsere RAP Anwendung fit für den Endanwender.

06.05.2025

RAP - Festwert-Filter

Kategorie - ABAP

Wie verwendest du Festwerte aus einer Domäne für einen Filter und passt diesen nach deinen Bedüfnissen in RAP an? Mehr dazu hier.

02.05.2025

RAP - Custom Pattern (Verhalten)

Kategorie - ABAP

In diesem Artikel erweitern wir das Custom Pattern in RAP um zusätzliche Daten und Verhalten. Damit können wir Mehrwerte in der Implementierung schaffen.

29.04.2025