# 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.

- Author: Ertugrul Balveren, Balsoft GmbH
- Published: 2026-10-12
- Language: German
- Tags: Dynamics 365 F&O, X++, Database refresh, Business events, Azure DevOps, Pipelines, Open source
- Canonical: https://balsoft.de/de/blog/balsoft-data-refresh

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**.

> **Open Source unter der MIT-Lizenz:** Modell, Einrichtungsanleitung und eine Beispiel-Pipeline für Azure DevOps liegen auf [GitHub](https://github.com/balsoft-gmbh/d365fo-database-refresh). Setzen Sie es in Ihren Projekten ein, passen Sie es an, geben Sie es weiter. Keine Lizenzgebühr, keine Registrierung.

## Was eine Kopie hinterlässt

Microsoft dokumentiert, was ein [Database Refresh](https://learn.microsoft.com/de-de/dynamics365/fin-ops-core/dev-itpro/database/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:

- Nach der Kopie: Alle Benutzer außer Admin sind deaktiviert. Was Balsoft Data Refresh macht: **Benutzer aktivieren**. Aktiviert die Tester und Key User dieser Umgebung.
- Nach der Kopie: Tester haben nur ihre Rollen aus der Produktion. Was Balsoft Data Refresh macht: **Sicherheitsrollen zuweisen**. Ergänzt die Rollen, die sie zum Testen brauchen.
- Nach der Kopie: Offene Workflowinstanzen kommen aus der Produktion mit. Was Balsoft Data Refresh macht: **Offene Workflows abbrechen**. Stoppt Genehmigungen, die zur Produktion gehören.
- Nach der Kopie: SMTP-Relay, E-Mail-Adressen und Druckeinstellungen fehlen; Schnittstellen-URLs zeigen noch auf die Produktion. Was Balsoft Data Refresh macht: **Feldwerte setzen**. Schreibt die Werte dieser Umgebung in beliebige Tabellenfelder.
- Nach der Kopie: Endpunkte für Business Events und Data Events sind entfernt. Was Balsoft Data Refresh macht: **Business-Event-Endpunkte anlegen**. Legt sie neu an und aktiviert ihre Ereignisse.
- Nach der Kopie: Alle Batchjobs stehen auf Zurückhalten. Was Balsoft Data Refresh macht: **Batchjobs freigeben**. Setzt die Jobs, die laufen sollen, wieder auf Warten.
- Nach der Kopie: Die Sandbox trägt die vollen Produktivdaten. Was Balsoft Data Refresh macht: **Daten bereinigen**. Löscht alte Journale und leert Staging-Tabellen.
- Nach der Kopie: Nach jeder Kopie muss sich jemand anmelden und all das von Hand erledigen. Was Balsoft Data Refresh macht: **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.

> **Kopieren und vorbereiten in einer Pipeline:** Das ist der wichtigste Teil. Die Beispiel-Pipeline im Repository kopiert die Produktion über Ihre Sandbox und ruft danach im selben Lauf den Service von Balsoft Data Refresh auf, der jeden Schritt aus der Liste oben erledigt. Nach einer Kopie muss sich niemand anmelden, und die Pipeline schlägt fehl, wenn ein Schritt fehlschlägt. Sie starten sie vor einer Testphase von Hand oder jede Woche per Zeitplan. Wie das funktioniert, steht [weiter unten](#die-kopie-mit-einer-pipeline-automatisieren).

## 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.

![Formular Umgebungen der Datenbankaktualisierung mit PROD und UAT oben und den Aufgaben von UAT mit Reihenfolge darunter](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/environments-and-tasks.webp)

*Oben die Umgebungen, darunter die Aufgaben der gewählten Umgebung mit ihrer Reihenfolge. Einrichten öffnet die Einrichtung der gewählten Aufgabe.*

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.

![Zu aktivierende Benutzer für UAT: Brad, JanetS, MollyD und RichardC mit ihren Namen](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/users-to-enable.webp)

*Zu aktivierende Benutzer in der UAT: vier Key User aus den Contoso-Demodaten.*

### 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.

![Benutzerrollen für UAT: Brad und JanetS bekommen Purchasing agent, MollyD bekommt Accounts payable clerk](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/security-roles.webp)

*Zusätzliche Rollen für die UAT-Tester. Gespeichert wird der Rollenbezeichner, angezeigt der Rollenname.*

### 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.

![Abzubrechende Workflows für UAT: Purchase order workflow und Vendor invoice journal workflow, alle Unternehmen](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/workflows-to-cancel.webp)

*Offene Bestell- und Kreditorenrechnungsgenehmigungen aus der Produktion werden in der UAT abgebrochen.*

### 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.

![Einrichtung der Feldwerte von UAT mit Zeilen für SysEmailParameters, CustParameters und die Parameter von Balsoft Data Refresh](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/field-values.webp)

*Feldwerte von UAT: der SMTP-Relayserver, ein Debitorenparameter und die Aufbewahrungsdauer des Protokolls in Balsoft Data Refresh selbst.*

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.

![Business-Event-Endpunkte von UAT: Event-Grid-Endpunkt Orders-UAT mit drei Business Events: Freitextrechnung gebucht, Verkaufsrechnung gebucht, Kreditorenrechnung gebucht](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/business-events.webp)

*Oben die Endpunkte, darunter die Business Events des gewählten Endpunkts. Orders-UAT hat beim Speichern Microsofts Testereignis bestanden.*

![Dialog Neuer Endpunkt mit Endpunktname, Service-Bus-Warteschlange, Anwendungs-ID, Key-Vault-DNS-Name, Key-Vault-Geheimnisname und Name des Clientgeheimnisses](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/endpoint-dialog.webp)

*Der Endpunktdialog folgt dem von Microsoft: erst der Typ, dann die Verbindung und die Key-Vault-Authentifizierung.*

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.

![Freizugebende Batchjobs für UAT: E-mail distributor batch, Change based alerts und Workflow message processing, alle auf Zurückhalten](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/batch-jobs.webp)

*Drei Jobs gehen nach der Kopie wieder auf Warten. Die Statusspalte zeigt ihren aktuellen Stand.*

### 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.

![Bereinigungsregeln von UAT: InventJournalTable ältere Datensätze löschen mit 90 Tagen, RetailAsyncCustomer Tabelle leeren](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/cleanup-rules.webp)

*Bereinigungsregeln: Lagerjournale älter als 90 Tage löschen, eine Staging-Tabelle leeren.*

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`](https://github.com/balsoft-gmbh/d365fo-database-refresh/blob/main/Pipelines/copy-and-refresh.yml), die den ganzen Ablauf übernimmt:

1. **Freigeben**: Die Pipeline wartet auf eine Genehmigung an der Azure-DevOps-Umgebung der Sandbox, damit niemand die UAT aus Versehen überschreibt.
2. **Kopieren**: Die Aufgabe aus den Power Platform Build Tools kopiert die Produktion über die Sandbox.
3. **Warten**: Ein Skript holt ein Token für die Sandbox und wartet, bis Finance and Operations antwortet. Direkt nach einer Kopie kann das dauern.
4. **Ausführen**: Es ruft den Service der Datenbankaktualisierung mit dem Umgebungscode, der ID des Pipeline-Laufs und den Geheimnissen aus der Pipeline auf.
5. **Verfolgen**: Laufen Aufgaben im Batch weiter, fragt es den Jobstatus ab, bis der Job fertig ist.
6. **Melden**: Es gibt jede Aufgabe mit ihrem Status aus und lässt die Pipeline fehlschlagen, wenn der Job nicht erfolgreich war. So weiß das Team Bescheid, bevor es die Tester merken.

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:

`copy-and-refresh.yml`:

```yaml
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`:

`run-request.json`:

```json
{
  "_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.

![Arbeitsbereich Datenbankaktualisierung mit Aktualisierungsjobs, den Aufgaben des gewählten Jobs und ihren Meldungen](https://stbalsoftweb.blob.core.windows.net/blog/balsoft-data-refresh/workspace.webp)

*Jeder Lauf, aus der Pipeline oder über das Menü, landet im Arbeitsbereich: der Job, seine Aufgaben und die Meldungen jeder Aufgabe.*

## 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:

`BDRTaskTypeBusinessEvents.xpp`:

```xpp
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](https://github.com/balsoft-gmbh/d365fo-database-refresh). 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](https://balsoft.de/de/contact).
