- Dynamics 365 F&O
- X++
- Database refresh
- Business events
- Azure DevOps
- Pipelines
- Open source
Balsoft Data Refresh: D365 F&O nach jeder Datenbankkopie vorbereiten
Benutzer, Rollen, SMTP, Endpunkte, Batchjobs, Bereinigung: Open-Source-Modell und Kopier-Pipeline bereiten D365 F&O nach jedem Refresh vor.
Auf dieser Seite+
Jeder Database Refresh endet gleich. Die Produktivdaten sind in der UAT-Sandbox angekommen, und dann verbringt jemand die nächste Stunde in der Systemverwaltung: die Tester wieder aktivieren, ihnen ihre Rollen zurückgeben, SMTP-Server und Schnittstellen-URLs auf die Testsysteme stellen, die Business-Event-Endpunkte neu anlegen, die Batchjobs freigeben, die laufen sollen, und den Rest angehalten lassen. Wer das von Hand macht, vergisst etwas. Eine vergessene SMTP-Einstellung schickt Testmails an echte Kunden. Eine vergessene URL schickt Testaufträge an das produktive Lager.
Diesen Schritt erledigen wir seit Jahren für unsere Kunden mit eigenen Werkzeugen, nach jeder Kopie. Jetzt haben wir diese Werkzeuge als ein sauberes Produkt neu gebaut und uns entschieden, es der Dynamics-365-Community zu geben: Balsoft Data Refresh.
Was eine Kopie hinterlässt
Microsoft dokumentiert, was ein Database Refresh bewusst nicht kopiert oder zurücksetzt, damit sich eine Sandbox direkt nach der Kopie nicht wie die Produktion verhält. Als Standard ist das richtig, aber die Arbeit danach ist für eine Umgebung immer dieselbe, und Microsoft überlässt sie Ihnen. Balsoft Data Refresh schließt jede dieser Lücken, und die letzte Zeile macht es für jeden Release-Prozess nutzbar:
Alle Benutzer außer Admin sind deaktiviert.
Benutzer aktivieren
Aktiviert die Tester und Key User dieser Umgebung.
Tester haben nur ihre Rollen aus der Produktion.
Sicherheitsrollen zuweisen
Ergänzt die Rollen, die sie zum Testen brauchen.
Offene Workflowinstanzen kommen aus der Produktion mit.
Offene Workflows abbrechen
Stoppt Genehmigungen, die zur Produktion gehören.
SMTP-Relay, E-Mail-Adressen und Druckeinstellungen fehlen; Schnittstellen-URLs zeigen noch auf die Produktion.
Feldwerte setzen
Schreibt die Werte dieser Umgebung in beliebige Tabellenfelder.
Endpunkte für Business Events und Data Events sind entfernt.
Business-Event-Endpunkte anlegen
Legt sie neu an und aktiviert ihre Ereignisse.
Alle Batchjobs stehen auf Zurückhalten.
Batchjobs freigeben
Setzt die Jobs, die laufen sollen, wieder auf Warten.
Die Sandbox trägt die vollen Produktivdaten.
Daten bereinigen
Löscht alte Journale und leert Staging-Tabellen.
Nach jeder Kopie muss sich jemand anmelden und all das von Hand erledigen.
Von außen starten, mit einem Serviceaufruf
Jedes System, das eine HTTP-Anfrage senden kann, führt alle Aufgaben aus: Azure DevOps, GitHub Actions, ein PowerShell-Skript oder Ihr eigenes Werkzeug. Der Aufruf liefert das Ergebnis jeder Aufgabe zurück.
Einmal einrichten, in der Produktion
In Finance and Operations heißt die Funktion Datenbankaktualisierung (englisch Database refresh). Sie hat ein eigenes Modul in der Navigation und einen Arbeitsbereich.
Die Einrichtungstabellen werden mit der Datenbank kopiert. Sie pflegen die Einrichtung aller Umgebungen also in der Produktion, und jede Kopie bringt sie mit. In der Zielumgebung führt Balsoft Data Refresh nur den Teil aus, der zu dieser Umgebung gehört.
Umgebungen werden so erkannt, wie Microsoft es in den Parametern für Überwachung und Telemetrie macht: über die Umgebungs-ID (die Power-Platform-Umgebungs-ID oder die LCS-Umgebungs-ID) und einen Umgebungsmodus. Aktuelle Umgebung hinzufügen trägt die ID der Instanz ein, auf der Sie gerade sind. Jede Umgebung bekommt ihre Aufgaben, die Sie aktivieren und in eine Reihenfolge bringen.

Eine fehlgeschlagene Aufgabe stoppt den Job nur, wenn Beim ersten Fehler anhalten gesetzt ist. Jeder Lauf wird als Job mit dem Ergebnis jeder Aufgabe und ihren Meldungen protokolliert.
Die Aufgaben im Einzelnen
Jede Aufgabe hat ein eigenes kleines Einrichtungsformular, das Sie mit Einrichten an der Aufgabe öffnen. Hier steht, was jede Aufgabe macht und wann Sie sie brauchen.
Benutzer aktivieren
Nach einer Kopie kann sich nur Admin anmelden. Diese Aufgabe aktiviert die Benutzer, die Sie für die Umgebung eintragen, etwa die Key User und Tester der UAT. Alle anderen Benutzer behalten ihren Status. Produktive Benutzer, die in der Sandbox nicht arbeiten sollen, bleiben also deaktiviert. Die Einrichtung ist ein Raster mit der Benutzer-ID.

Sicherheitsrollen zuweisen
Tester brauchen in der UAT oft Rollen, die sie in der Produktion nicht haben, zum Beispiel ein Key User, der den Genehmigungsworkflow als Genehmiger testet. Diese Aufgabe weist Rollen je Benutzer und Umgebung zu oder aktiviert eine deaktivierte Zuweisung. Rollen werden über ihren AOT-Namen gespeichert, der in jeder Umgebung gleich ist, anders als die Datensatz-ID. Das Formular zeigt die Rollenbezeichnung, Sie wählen also weiterhin „Kreditorenbuchhalter“ und keinen technischen Namen.

Offene Workflows abbrechen
Die Kopie bringt jede offene Workflowinstanz aus der Produktion mit. Laufen sie in der Sandbox weiter, bekommen Genehmiger Aufgaben und Mails zu Belegen, die zur Produktion gehören. Diese Aufgabe bricht die offenen Instanzen der eingetragenen Workflows ab, oder aller Workflows, wenn die Zeile keinen Workflow nennt, in allen oder in ausgewählten Unternehmen. Sie wirkt nur auf das, was eingerichtet ist: Ohne Zeile ändert sie nichts.

Feldwerte setzen
Diese Aufgabe ersetzt das Datenpaket. Sie schreibt einen beliebigen Wert in ein beliebiges Tabellenfeld: den SMTP-Relayserver, die URL einer Schnittstelle, eine Dateifreigabe, einen Parameter, der im Test anders sein muss. Ein optionales Nur wenn Feld mit Den Wert hat beschränkt die Änderung auf passende Datensätze, und jede Zeile hat Alle Unternehmen oder eine Liste von Unternehmen.

Jede Zeile wird beim Speichern geprüft und nicht erst beim nächsten Refresh: Das Feld muss existieren und darf kein Systemfeld sein, der Wert muss zum Feldtyp passen, und eine Tabelle, die keine Daten speichert, wird abgelehnt. Für einen vertraulichen Wert, etwa das Passwort einer Schnittstelle, nennt die Zeile nur ein Pipeline-Geheimnis, und die Pipeline übergibt den Wert zur Laufzeit.
Business-Event-Endpunkte anlegen
Vor den Endpunkten graut es nach einer Kopie den meisten, weil jeder einen Key Vault, eine App-Registrierung und einen geheimen Clientschlüssel braucht. Diese Aufgabe legt Endpunkte aller Azure-Typen an (Service-Bus-Warteschlange und -Thema, Event Grid, Event Hub, Blob Storage), über Microsofts eigene Endpunktklassen, und aktiviert ihre Business Events in den Unternehmen des Endpunkts. Sie erscheinen im Standard-Arbeitsbereich für Business Events genau so, als hätten Sie sie dort angelegt.


Der geheime Clientschlüssel wird nie gespeichert. Die Einrichtungszeile benennt ihn nur, und die Pipeline übergibt den Wert beim Serviceaufruf. Beim Speichern eines Endpunkts schickt Balsoft Data Refresh Microsofts Testereignis an ihn. Ein Tippfehler im Namen der Warteschlange fällt so schon bei der Einrichtung auf und nicht erst nach dem nächsten Refresh.
Batchjobs freigeben
Die Kopie setzt jeden Batchjob auf Zurückhalten, und das ist gut so: Es läuft nichts, was nicht laufen soll. Einige Jobs müssen in der UAT aber laufen, etwa die Workflowverarbeitung, der E-Mail-Verteiler oder die Warnungen. Tragen Sie sie hier ein, und die Aufgabe setzt sie wieder auf Warten. Alle anderen bleiben angehalten.

Daten bereinigen
Eine UAT-Kopie der Produktion ist groß, und Tester brauchen selten fünf Jahre Erfassungsjournale. Bereinigungsregeln kennen drei Modi: Ältere Datensätze löschen behält eine Anzahl Tage, Alle Datensätze löschen leert eine Tabelle in allen oder in ausgewählten Unternehmen, und Tabelle leeren (alle Unternehmen) leert sie für alle Unternehmen auf einmal. Löschaktionen werden standardmäßig befolgt, die Zeilen eines Journals gehen also mit seinem Kopf.

Wählbar sind nur Tabellen der Gruppen Transaktion, Arbeitsblatt, Staging und Sonstiges. Stammdaten und Parameter stehen nicht auf der Liste. Lange Bereinigungen laufen im Batch, und die Aufgaben danach folgen im selben Batchjob, damit die Reihenfolge stimmt.
Die Kopie mit einer Pipeline automatisieren
Sie können einen Lauf über das Menü starten, gebaut ist Balsoft Data Refresh aber vor allem für eines: einen Refresh, der läuft, ohne dass jemand Hand anlegt. Das Repository enthält eine Beispiel-Pipeline für Azure DevOps, Pipelines/copy-and-refresh.yml, die den ganzen Ablauf übernimmt:
Freigeben
Kopieren
Warten
Ausführen
Verfolgen
Melden
Starten Sie sie vor einer Testphase von Hand, oder aktivieren Sie den Zeitplan für einen wöchentlichen Refresh. Der Kern der Pipeline ist kurz:
stages: - stage: Copy jobs: - deployment: copy environment: CONTOSO-UAT # Genehmigung, bevor die Sandbox überschrieben wird timeoutInMinutes: 360 strategy: runOnce: deploy: steps: - task: PowerPlatformToolInstaller@2 - task: PowerPlatformCopyEnvironment@2 inputs: authenticationType: PowerPlatformSPN PowerPlatformSPN: CONTOSO-PROD # Dienstverbindung der Quelle TargetEnvironmentUrl: https://contoso-uat.crm4.dynamics.com CopyType: FullCopy - stage: Refresh dependsOn: Copy jobs: - job: refresh steps: - task: PowerShell@2 inputs: pwsh: true filePath: Pipelines/scripts/Invoke-DatabaseRefresh.ps1 arguments: >- -FinOpsUrl https://contoso-uat.sandbox.operations.eu.dynamics.com -TenantId $(TenantId) -ClientId $(ClientId) -EnvironmentId UAT -SecretNames ServiceBusAppSecret -RequestId $(Build.BuildId) env: BDR_CLIENT_SECRET: $(ClientSecret) BDR_SECRET_ServiceBusAppSecret: $(ServiceBusAppSecret)Das Skript schickt diese Anfrage an POST /api/services/BDRServices/BDRService/run:
{ "_request": { "EnvironmentId": "UAT", "TaskTypeNames": [], "RequestId": "<Pipeline-Lauf-ID>", "RunInBatch": false, "ReturnResultOnFailure": true, "Secrets": [ { "Name": "ServiceBusAppSecret", "Value": "<aus der Pipeline>" } ] }}Ein leeres TaskTypeNames führt alle aktiven Aufgaben der Umgebung aus. Das Ergebnis listet jede Aufgabe mit Status, Anzahl geänderter Datensätze und Meldung. Ein wiederholter Aufruf mit derselben RequestId liefert den ersten Job zurück, statt neu zu laufen. Ein Retry nach einem Timeout ist damit sicher. Ohne ReturnResultOnFailure kommt ein fehlgeschlagener Job als HTTP-Fehler zurück. Auch eine einfache Pipeline, die nur den Statuscode prüft, gibt die Umgebung nach einem fehlgeschlagenen Lauf also nicht frei.
Vor dem ersten Lauf brauchen Sie drei Dinge, die alle oben in der Pipeline-Datei stehen:
- Eine Power-Platform-Dienstverbindung für die Quellumgebung, mit einem Dienstprinzipal, der Umgebungen kopieren darf.
- Eine Variablengruppe
DatabaseRefresh, am besten mit Azure Key Vault verknüpft, mit Mandanten-ID, Client-ID und geheimem Clientschlüssel einer Entra-ID-Anwendung, dazu ein Geheimnis je Geheimnis, das Ihre Einrichtung nennt. Registrieren Sie diese Anwendung unter Systemverwaltung > Einrichtung > Microsoft Entra ID-Anwendungen mit einem Benutzer, der die Rolle Administrator Datenbankaktualisierung hat. Weil die Einrichtung aus der Produktion kommt, registrieren Sie sie dort, und die Kopie bringt sie mit. - Eine Azure-DevOps-Umgebung für die Sandbox mit einer Genehmigung.
Die Kopie einer Finance-and-Operations-Umgebung kann mehrere Stunden dauern, und ein Job auf einem von Microsoft gehosteten Agent endet nach 6 Stunden. Für längere Kopien nehmen Sie einen selbst gehosteten Agent, oder Sie starten die Kopie im Power Platform Admin Center und lassen die Pipeline mit skipCopy laufen, dann führt sie nur den Refresh aus. Das Skript funktioniert auch allein, auf jedem Rechner mit PowerShell. Für eine LCS-Umgebung ersetzen Sie die Kopierstufe durch einen Refresh über die LCS Database Movement API, die Refresh-Stufe bleibt gleich.

Sicherheit zuerst
Ein Werkzeug, das in eine frisch kopierte Datenbank schreibt, darf nicht am falschen Ort laufen:
- Es läuft nie in einer Umgebung mit dem Modus Produktion. Die Prüfung steckt im Job selbst und gilt deshalb auch für Serviceaufrufe.
- Es läuft nur, wenn die aktuelle Instanz als Umgebung eingerichtet ist, und die Umgebungs-ID im Serviceaufruf muss zur Instanz passen.
- Benutzer aktivieren und Offene Workflows abbrechen wirken nur auf das, was eingerichtet ist. Ohne Einrichtung ändern sie nichts.
- Ein Job je Umgebung gleichzeitig. Ein zweiter Aufruf wird abgelehnt, solange ein Job läuft oder geplant ist.
Wie wir es testen
Nach jedem Release wird das Modell in eine Unified-Developer-Umgebung deployt, und eine Suite mit mehr als 300 End-to-End-Prüfungen läuft über den Webclient und den Service dagegen: jedes Einrichtungsformular, jede Validierung, echte Endpunkte aller Azure-Typen mit Microsofts Testereignis, Serviceläufe und das Aufräumen von allem, was die Tests angelegt haben.
Diese Suite hat einen Fehler gefunden, den Sie kennen sollten, wenn Sie X++ gegen Business Events schreiben. BusinessEventsEndpoint::findByName geht über den Datensatzcache der Endpunkttabellen. Nachdem ein Endpunkt im Arbeitsbereich für Business Events gelöscht wurde, konnte die Methode den gelöschten Datensatz noch zurückgeben, und unsere Aufgabe übersprang den Endpunkt mit „existiert bereits“. Das Lesen der Tabelle mit ausgeschaltetem Cache hat es behoben:
private RefRecId existingEndpoint(BusinessEventsEndpointName _endpointName){ BusinessEventsEndpoint standardEndpoint; standardEndpoint.disableCache(true); select firstonly RecId from standardEndpoint where standardEndpoint.Name == _endpointName; return standardEndpoint.RecId;}So bekommen Sie es
Modell, Einrichtungsanleitung, Kopier-Pipeline sowie Build- und Release-Pipeline liegen auf GitHub. Modell deployen, die Rolle Administrator Datenbankaktualisierung zuweisen, eine Umgebung in der Produktion einrichten und den nächsten Refresh die Pipeline machen lassen.
Die Aufgabentypen sind Plugins, gebaut wie Microsofts Datenarchivierung. Wenn Ihnen eine Aufgabe fehlt, ergänzen Sie sie in Ihrem eigenen Modell, ohne unseres zu ändern. Fehlermeldungen und Ideen nehmen wir gern als GitHub-Issue entgegen. Wenn Sie Hilfe brauchen, Balsoft Data Refresh in Ihren Release-Prozess einzubauen, sprechen Sie uns an.