Zum Inhalt wechseln

Einrichten des Power Automate-Flows für Dataverse Auditing

Technology

27 April 2023 - 5 Minuten lesen

3135 Blog Post Setting Up The Power Automate Flow 416X300
Amadeusz Nowak Software Developer  

Er ist ein Power Platform Entwickler mit über 5 Jahren Erfahrung. Außerhalb der Bürozeiten ist Amadeusz ein Amateur-Fußballanalyst und ein begeisterter PC-Bauer.

Alle Beiträge von Amadeusz anzeigen

1394 DE Resources Thumbs

Teilen

Dies ist der vierte Teil meines Leitfadens zu benutzerdefinierten Überwachungsprotokollen in PowerApps. Im vorherigen Teil haben wir mit der Arbeit an unserem automatisierten Ablauf begonnen, eine Verbindung mit Key Vault hergestellt und Rohprotokolle aus Dataverse abgerufen. In diesem Teil werden wir die Basis des Flows fertigstellen.

A big loop

Erinnern Sie sich an die Array-Variable, die wir zu Beginn erstellt haben? Jetzt gilt es, davon Gebrauch zu machen.

Beginnen wir damit, die Aktion „Apply to each“ hinzuzufügen und sie über die Array-Variable auszuführen.

Jetzt setzen Sie Ihre strOld- und strNew-Variablen mit alten und neuen Werten für das aktuelle Element in der Schleife.

Verwenden Sie dazu Folgendes:

outputs('Compose_-_OldValues')?[item()?['logical_name']]

Auspacken.

Wir extrahieren den Wert aus dem JSON-Objekt aus dem Parameter gleich dem aktuellen Element „logical_name“.

Dasselbe muss für strNew wiederholt werden:

outputs('Compose_-_NewValues')?[item()?['logical_name']]

Bevor Sie mit diesen Rohwerten arbeiten, müssen Sie überprüfen, ob Änderungen an der aktuellen Spalte aufgetreten sind. Erstellen Sie dazu eine einfache Bedingung.

Jetzt prüfen Sie, ob „logical_name“ des aktuellen Elements mindestens einmal im JSON vorkommt, das von der Aktion „HTTP – Audit-Protokoll abrufen“ empfangen wurde. Verwenden Sie:

string(body('HTTP_-_get_audit_log'))

 

beinhaltet

 

items('Apply_to_each_-_arrColumns')?['logical_name']

 

Sie möchten nichts tun, wenn die Bedingung falsch ist, also sollten Sie den „Wenn nein“-Balken leer lassen. Konzentrieren wir uns auf das „If Yes“.

Umgang mit unterschiedlichen Datentypen

Da das Überwachungsprotokoll nur Rohwerte, die sich geändert haben zurückgibt, müssen Sie etwas mehr Arbeit aufwenden, um das System benutzerfreundlicher zu gestalten. Sie werden je nach Spaltentyp unterschiedliche Strategien zum Extrahieren von Werten verwenden. Aus diesem Grund wurden bei der Definition des Arrays zusätzliche Metadaten zu unseren Spalten benötigt.

Um sich für die richtige Strategie für die aktuelle Iteration zu entscheiden, müssen Sie die Operation „Switch“ verwenden. Als Argument für diese Aktion möchten Sie den „Type“-Wert des aktuellen Objekts in arrColumns verwenden. 

Dies ist der Ausdruck, den 'Switch' als Argument erhält: 

items('Apply_to_each_-_arrColumns')?['type']

Jeder Spaltentyp hat einen eigenen Balken. Lassen Sie uns im Detail über sie besprechen. 

Auswahl 

Wie in den vorherigen Teilen dieses Guides müssen Sie erneut eine HTTP-Anforderung verfassen. Diesmal, um Beschriftungen aus der Auswahlspalte abzurufen. 

Auch hier beginnen Sie mit der Variablen, die die Umgebungs-URL speichert, als Nächstes fragen Sie nach globalen OptionSets-Definitionen und filtern dieses Array nach dem logischen Namen des OptionSets. Die Anfrage sieht so aus: 

@{parameters('EnvironmentURL(anowak_EnvironmentURL)')}api/data/v9.0/GlobalOptionSetDefinitions(Name='@{items('Apply_to_each_-_arrColumns')?['related']}')

 Mehr dazu 

Dann senden Sie diese Anfrage genauso wie zuvor. Weitere Informationen finden Sie im vorherigen Teil auf unserem Blog – Abrufen von Dataverse-Audits in Power Automate. 

Lassen Sie uns nun überprüfen, ob in dieser Spalte zuvor ein Wert vorhanden war. 

Wenn das der Fall war („If Yes“), müssen Sie das von der http-Anfrage erhaltene Array nach der Variable filtern.

Your filter looks like this:

From:

body('HTTP_-_get_choice_options')?['Options']

 

string(item()['Value'])

is equal to

variables(‘strOld’)

Now, it’s time to parse the result of this filter action.

Auch wenn Sie nur ein Ergebnis der Filteraktion erhalten, müssen Sie den Ausdruck „first()“ verwenden. Andernfalls zwingt Power Automate Sie, die Aktion „Parse JSON“ in eine unnötige Schleife zu versetzen.

Inhalt: 
first(body('Filter_array_-_old_choice'))

Schema: 

{

    "type": "object",

    "properties": {

        "Value": {

            "type": "integer"

        },

        "Label": {

            "type": "object",

            "properties": {

                "LocalizedLabels": {

                    "type": "array",

                    "items": {

                        "type": "object",

                        "properties": {

                            "Label": {

                                "type": "string"

                            }

                        },

                        "required": [

                            "Label"

                        ]

                    }

                }

            }

        }

    }

}

Schließlich ist es an der Zeit, der strOld-Variablen einen neuen Wert zuzuweisen.

Expression: 

first(body('Parse_JSON_-_old_choice')?['Label']?['LocalizedLabels'])?['Label']

So sollte Ihr ‘If Yes’-Balken aussehen. 

Was ist mit dem „If No“-Balken? Das ist einfach. Sie weisen der strOld-Variablen einfach ‚leer‘ zu.

Lassen Sie uns nun diese Struktur für die Variable strNew wiederholen.

 

Lookups

 

Lookups sind etwas einfacher, aber sie folgen einer ähnlichen Logik. Sie beginnen damit, eine Bedingung zu erstellen, um zu prüfen, ob strOld leer ist.

In der Verzweigung „Wenn Ja“ erhalten Sie die Zeile nach ID von der zugehörigen Entität.

Table name – enter custom: 

items('Apply_to_each_-_arrColumns')?['related_table']

Row ID: 

Variables{‘strOld’)

Wenn Sie alle Spalten aus der Tabelle erhalten haben, können Sie einen neuen Wert auf strOld setzen.

Value: 

body('Get_a_row_by_ID_-_old_lookup')?[item()?['related_name']]

Damit ist der „If Yes“-Balken abgeschlossen.

Wie zuvor hat der „If No“ nur eine Aktion – setzen Sie die strOld-Variable auf „leer“.

Noch einmal, Sie werden dasselbe für strNew wiederholen.

Dates

Je weiter Sie im Prozess sind, desto einfacher wird es. Beginnen Sie wieder mit der Bedingung, aber dieses Mal haben Sie nur eine Aktion im „If Yes“-Balken.

Im Falle von ‘If Yes’, können Sie dem strOld einen neuen Wert zuordnen.

Genutze Expression: 

formatDateTime(outputs('Compose_-_OldValues')?[item()?['logical_name']], 'yyyy-MM-dd')

Sie können natürlich auch ein anderes Format nutzen.

‘If no’ wird immer gleich sein, also müssen Sie dies jetzt nur noch für strNew wiederholen.

Status

Status sind der einzige Switch-Branch, bei dem Sie nicht prüfen müssen, ob die Variablen leer sind, da Datensätze immer einen Status haben. Sie müssen nur den Variablen strOld und strNew neue Werte zuweisen.

 

strOld: 
if(equals(outputs('Compose_-_OldValues')?[item()?['logical_name']],0),'Active','Inactive')

strNew: 
if(equals(outputs('Compose_-_NewValues')?[item()?['logical_name']],0),'Active','Inactive')

Default 

Andere Datentypen benötigen keine besondere Behandlung, also behandeln wir sie im Default-Zweig. Die einzige Maßnahme, die Sie ergreifen müssen, besteht darin, den Variablenwert als „leer“ zuzuweisen, wenn sie keine Werte enthalten.

Änderungen anhängen

Es fühlt sich wie eine Ewigkeit an, aber wir befinden uns immer noch im „If Yes“-Zweig, um zu prüfen, ob das aktuelle Element in der Schleife im Audit-Log geändert wurde. Glücklicherweise ist es fast die Ziellinie. In diesem Zweig müssen Sie die Variable strChanges anhängen. 

Anzuhängender Wert:

@{items('Apply_to_each_-_arrColumns')?['display_name']} changed from '@{variables('strOld')}' to '@{variables('strNew')}'

Das wird die letzte Action in diesem Zweig.

Variablen bereinigen

Was übrig bleibt, ist, die Variablen strOld und strNew vor der nächsten Iteration zu bereinigen.

Kann ich endlich mit dem Eintrag beginnen?

Ja! Der letzte Schritt dieses Ablaufs besteht darin, eine neue Zeile zu erstellen.

Eine kurze Erinnerung an die Spalten, die ich in mein Überwachungsprotokoll aufgenommen habe:

  • Log – Autonumber; Prefix – ‘Log’; Minimum number of digits = 4; seed = 0; 
  • Changes – Multiple lines of text; Text 
  • Context – Choice (‘New record’, ‘Update’, ‘Deletion’) 
  • Changed by – Lookup (User) 
  • Changed on – Date and time 
  • Record – Lookup (Cast – my custom entity on which I want to track changes) 

Wie Sie auf dem obigen Bildschirm sehen können, habe ich mein Audit-Protokoll mit Informationen angereichert, dass es sich um eine Aktualisierung handelt, aber Sie können einen robusteren Datenanreicherungsprozess basierend auf dem Flow-Ausführungskontext erstellen.

Sie fragen sich vielleicht, wo die Spalte „Protokoll“ ist. Ich habe es als "Unternehmen empfohlen" eingestellt. Auf diese Weise muss ich keinen Wert in meinem Flow angeben, aber da es sich um ein Feld mit automatischer Nummerierung handelt, wird es automatisch zugewiesen.

Während die meisten Felder unkompliziert sind, müssen Sie sich die Nachschlagespalten genauer ansehen.

Es gibt zwei davon: „Geändert von“ und „Eintrag“.

„Geändert von“ ist eine Suche nach der Systemspalte namens „Benutzer“. Um den Wert richtig zuzuweisen, müssen Sie diesen Ausdruck verwenden:

systemusers([GUID of user])

In meinem Fall ist es eine GUID des Benutzers, der Änderungen vorgenommen hat, die den Flow ausgelöst haben, also verwende ich „geändert von“ dynamischen Inhalt aus dem Auslöserkontext.

„Record“ ist eine Suche nach der benutzerdefinierten Entität „Cast“, an der ich Änderungen nachverfolge. Der Ausdruck hier wird sein:

[publisher logical name]_[plural name of entity]([unique identifier of the record])

 Also, in meinem Fall:

[publisher logical name] – anowak 

[plural name of entity] – casts (Ich weiß, es gibt nicht die Pluralform von ‘Cast’ aber so Dataverse) 

[unique identifier of the record] – GUID des Datensatzes, der aktualisiert wurde

 Was ich noch nutze:

anowak_casts(@{triggerOutputs()?['body/anowak_castid']})

 Und das ist das Ende des vierten Teils meines Guides über Dataverse-Auditing. Das System ist startklar! Im letzten Teil fasse ich die bisherige Arbeit zusammen, diskutiere Vor- und Nachteile dieser Lösung und denke über mögliche Erweiterungen nach.

1394 DE Resources Thumbs
Amadeusz Nowak Software Developer  

Er ist ein Power Platform Entwickler mit über 5 Jahren Erfahrung. Außerhalb der Bürozeiten ist Amadeusz ein Amateur-Fußballanalyst und ein begeisterter PC-Bauer.

Alle Beiträge von Amadeusz anzeigen

Was Sie noch interesieren könnte

Kontakt

Starten Sie Ihr Projekt mit Objectivity

CTA Pattern - Contact - Middle