Das ist eine für den Ausdruck optimierte Ansicht des gesamten Kapitels inkl. Unterseiten.
Druckvorgang starten.
Zur Standardansicht zurückkehren.
Versionshistorie
Release-Dokumentation aller Versionen der dsyr.DataBridge — Änderungen, neue Funktionen und Installationshinweise.
Hier findet sich die Release-Dokumentation für alle Versionen der dsyr.DataBridge.
Jede Version beschreibt die wesentlichen Änderungen aus Anwender-Sicht sowie
Installationshinweise für Administratoren, die ein bestehendes System aktualisieren. Die
Details zu etwaigen Breaking Changes stehen jeweils im Abschnitt Installationshinweise
der verlinkten Release-Seite.
| Release | Schwerpunkt | Breaking Change |
|---|
| v2.3 | Tabellen- und Spalten-Metadaten der SQL-Connectoren (MSSQL, MySQL, Oracle, PostgreSQL) über den MCP-Server, Mapping-Abfrage per Name, schlankeres NAV-Logging, Managed Identity (System/User-assigned) für D365BC und D365CE mit neuem Verbindungsfeld authmethod; für Entwickler: lokale Podman-Testumgebung mit HTTP-Mocks, Service-Bus-Emulator und Debug-Modus | ✅ |
| v2.2 | Neuer OpenAPI-Connector, eingebauter MCP-Server für KI-Assistenten, Action-Jobs, System-assigned Managed Identity für die Function App, Verbesserungen am Grafana-Dashboard | ✅ |
| v2.1 | Erweiterte Lookup-Funktionen, Sampling von Abhängigkeiten, Grafana-Dashboard, Watermark-Korrekturen | ✅ |
| v2.0 | Umstellung auf .NET 10, Containerisierung, gepuffertes Logging, Custom Metrics | ❗ |
| Ältere Releases | Migrationshinweise für die Übergänge 1.0 → 1.1 und 1.1 → 2.0 | ❗ |
Vor einem Update lesen
Die Abschnitte Installationshinweise der jeweiligen Version enthalten die Details zu
Breaking Changes und notwendigen Migrationsschritten. Beim Überspringen von Versionen sind
die Hinweise aller dazwischenliegenden Releases zu beachten — die Spalte oben zeigt
nur, ob ein Übergang überhaupt einen Breaking Change enthält, keine vollständige Liste.
1 - Release v2.3
Managed Identity (system- und benutzer-zugewiesen) für D365BC und D365CE, Tabellen- und Spalten-Metadaten der SQL-Connectoren (MSSQL, MySQL, Oracle, PostgreSQL) über den MCP-Server, genauere Datentypen, Mapping-Abfrage per Name, schlankeres NAV-Logging, wieder funktionierendes Lesen aus PostgreSQL, MySQL und Oracle, behobene Abbrüche beim Schreiben von SQL-Datums-, Ganzzahl- und Fließkommafeldern nach BC/NAV/CE/OpenAPI und eine lokale Podman-Testumgebung mit Datenbanken, HTTP-Mocks und einem Service-Bus-Emulator für BC, NAV und OpenAPI.
Was ist neu
Neue Funktionen
Metadaten-Abfrage für die SQL-Connectoren: Die MCP-Tools list_connector_tables und get_connector_table_schema funktionieren jetzt auch für MSSQL, MySQL, Oracle und PostgreSQL. Bisher war das nur für BC, NAV, CE (Dataverse) und OpenAPI möglich, bei SQL-Verbindungen brach der Aufruf mit einer Fehlermeldung ab. Geliefert werden Spaltenname, Typ, Nullable, maximale Länge, bei Dezimalspalten Precision und Scale sowie der Primary Key — direkt aus dem Datenbank-Katalog (INFORMATION_SCHEMA, bei Oracle USER_*/ALL_*-Views).
Über apiPath wird das Schema gewählt (MySQL: die Datenbank, Oracle: der Owner). Ohne Angabe gilt das Standard-Schema der Verbindung, sodass gleichnamige Tabellen in verschiedenen Schemas (z. B. dbo.Customers / archive.Customers) nicht vermischt werden. Die Metadaten werden zwischengespeichert; Schemaänderungen an der Datenbank werden erst nach einem Neustart der Function App sichtbar. Details: MCP-Server → Operationen.
Genaue .NET-Datentypen je Datenbank: Die Spaltentypen werden je Datenbank passend abgebildet — z. B. date als DateOnly, time als TimeSpan, Spalten mit Zeitzone als DateTimeOffset, Binärspalten als Byte[], MySQL BOOLEAN (tinyint(1)) als Boolean und Oracle NUMBER(p,0) je nach Stellenzahl als Int16/Int32/Int64. Die vollständige Übersicht steht unter MCP-Server → Operationen.
Managed Identity für D365CE (Dataverse): Die Verbindung kann statt über einen Connection-String mit Secret direkt über die Managed Identity der Function App aufgebaut werden. Dazu url (und optional clientid für eine benutzer-zugewiesene Identity) in der Connection angeben. Ein vorhandener connectionstring hat weiterhin Vorrang. Siehe D365CE.
Managed Identity für D365BC (Cloud): Neue Authentifizierungsart ManagedIdentity für HTTP-Konnektoren. Ohne clientId wird die system-zugewiesene, mit clientId die benutzer-zugewiesene Identity genutzt. Der Token wird automatisch erneuert, bevor er abläuft, und mit dem scope der Connection angefordert. Siehe D365BC.
Neuer Verbindungsparameter authmethod: Erlaubt es, die Authentifizierungsmethode ausdrücklich festzulegen (BasicAuthentication, OAuth2, APIKey, ManagedIdentity). Ohne Angabe bleibt das bisherige Verhalten unverändert. ManagedIdentity wird nie automatisch aus fehlenden Zugangsdaten abgeleitet, damit eine unvollständige Connection weiterhin sofort mit einem klaren Fehler abbricht. Siehe Verbindungen.
Fehlerbehebungen & Verbesserungen
Allgemein
- Felder fehlten gelegentlich in der Verarbeitung: Wurden die Mappings neu geladen, während gleichzeitig Änderungen gelesen oder Nachrichten verarbeitet wurden, konnte ein Job auf ein noch unvollständiges Mapping treffen. Einzelne Felder, z. B. die Kontaktnummer einer Firma, wurden dann nicht übertragen. Die Mappings werden jetzt vollständig aufgebaut und erst danach aktiv geschaltet.
- Service Bus: Skalierung ohne Managed Identity: Im schlüsselbasierten Modus (Standard,
enableManagedIdentity nicht gesetzt) setzt das Bicep-Deployment jetzt TARGET_BASED_SCALING_ENABLED=0. Der Host skaliert dann direkt über den Metrics Monitor, und die bisherige Warnung zum Target-based Scaling im Log entfällt. Siehe Umgebungsvariablen. - Mapping-Abfrage über den Namen: Das MCP-Tool
get_mapping und der HTTP-Endpunkt GET /mapping/{name} finden ein Mapping jetzt über seinen Namen — also den Namen, auf den ein Job verweist und unter dem list_mappings es auflistet. Bisher wurde nur der RowKey des ersten Feldeintrags verglichen, sodass ein Mapping über seinen Namen meist nicht gefunden wurde. Die bisherige Suche über den RowKey funktioniert weiterhin. get_connector_table_schema akzeptiert jetzt auch den kombinierten Tabellennamen: Bei BC/NAV/CE/OpenAPI wird der API-Pfad in Jobs/Mappings üblicherweise zusammen mit der Tabelle geschrieben (z. B. v2.0/customers). Wurde dieser kombinierte Wert unverändert als tableName übergeben und apiPath weggelassen, schlug die Metadaten-Abfrage mit einer schwer deutbaren Exception fehl (Could not read Metadata for path). Das Tool trennt den API-Pfad jetzt selbst ab, wenn apiPath leer bleibt und tableName einen / enthält — Aufrufe mit getrennten Parametern funktionieren unverändert.- Nachvollziehbare MCP-Aufrufe im Log: Jeder MCP-Aufruf schreibt eine Logzeile mit dem Namen der Operation und — wo vorhanden — dem gelesenen Job, Mapping bzw. der Connection und Tabelle, z. B.
MCP get_connector_table_schema: connection=oracle-dev, table=Account. Datensatzinhalte oder Zugangsdaten werden nicht geloggt. - Aktualisierte Abhängigkeiten (u. a.
Azure.Data.Tables, Azure.Messaging.ServiceBus, Azure.Security.KeyVault.Secrets 4.11.2, Microsoft.IdentityModel.Tokens, Microsoft.OData.Core/Microsoft.OData.Edm auf 9.0.0, Microsoft.Data.SqlClient 7.1.1, MySql.Data 26.10.0, Oracle.ManagedDataAccess.Core 23.26.400, Microsoft.OpenApi 3.11.0, ModelContextProtocol 2.3.0, Durable-Functions-Extension 1.20.1 — rein intern, keine Verhaltensänderung). System.Security.Cryptography.Xml steht auf 10.0.14 und schließt damit mehrere als „hoch“ eingestufte Sicherheitslücken der Vorversion.
D365CE (Dataverse)
- Fehlender oder inaktiver Alternativschlüssel wird nicht mehr als „Datensatz nicht gefunden“ gewertet: Ist der in
TargetKey verwendete Schlüssel in Dataverse nicht definiert oder nicht aktiv, bricht die Verarbeitung jetzt mit einem Fehler ab. Die Nachricht wird wiederholt und landet anschließend in der Dead-Letter-Queue. Bisher wurde der Datensatz in diesem Fall als nicht vorhanden behandelt und neu angelegt, was zu Dubletten führen konnte. Siehe D365CE. - Fehler beim Nachschlagen eines Datensatzes führten still zu falschen Daten: Schlug das Lesen des bestehenden Zieldatensatzes fehl, etwa durch Throttling (Service-Protection-Limits), Timeout, Netzwerk- oder Rechtefehler, wurde das bisher wie „Datensatz existiert nicht“ behandelt. Die Folgen blieben unbemerkt: Löschungen wurden übersprungen und die Nachricht als erledigt abgeschlossen, Felder mit leerem Quellwert wurden im Ziel nicht geleert, und Lookups mit
DoNotCreate konnten eine bestehende Referenz leeren. Jetzt gilt nur noch die Dataverse-Meldung „Datensatz nicht gefunden“ als solcher; jeder andere Fehler wird mit Details geloggt, die Nachricht wiederholt und notfalls in die Dead-Letter-Queue gelegt. - Nachgeschlagene Werte wurden nicht aktualisiert, wenn sie beim ersten Lesen noch fehlten: Lookups mit
UseCache (z. B. die BC-Kontaktnummer der Firma auf Kontakten und Verkaufschancen) speicherten auch ein leeres Ergebnis und behielten einen einmal gelesenen Wert bis zum Neustart der Function App. War die Nummer beim ersten Lesen noch nicht aus BC zurückgeschrieben, wurde das Feld deshalb auch danach leer übertragen. Leere Ergebnisse werden jetzt nicht mehr gespeichert, und beim Lesen der Änderungen ersetzt ein frisch gelesener Wert immer den gespeicherten. Nicht mehr vorhandene Datensätze werden aus dem Zwischenspeicher entfernt. - Boolean-Felder aus Ganzzahlen befüllen: Ja/Nein-Felder akzeptieren jetzt auch die Quelltypen
byte (z. B. SQL tinyint) und int32 (0 = Nein, sonst Ja). Statusfelder (statecode) akzeptieren zusätzlich byte.
BC, NAV & OpenAPI
- HTTP-Konnektoren (BC, NAV, OpenAPI) konnten nach dem Start dauerhaft ausfallen: Verarbeiteten mehrere Queue-Nachrichten gleichzeitig ihren ersten Aufruf an dasselbe Zielsystem, richteten sie den gemeinsamen HTTP-Client parallel ein. Das führte zu Fehlern wie
Object reference not set to an instance of an object oder This instance has already started one or more requests. Danach blieb der Client unvollständig eingerichtet (z. B. ohne Authentifizierung), und alle weiteren Nachrichten an dieses System schlugen bis zum Neustart der Function App fehl. Die Einrichtung ist jetzt gegen parallelen Zugriff geschützt, und eine fehlgeschlagene Einrichtung wird beim nächsten Aufruf wiederholt. - Update nach BC oder NAV schlug fehl, wenn ein Zielfeld dort bereits leer war: War ein Feld im bestehenden BC- oder NAV-Zieldatensatz
null (z. B. ein noch nicht gesetztes Abschlussdatum) und hatte sich irgendein anderes Feld des Datensatzes geändert, brach die Aktualisierung mit einer NullReferenceException ab. Der interne Änderungsvergleich ging fälschlich davon aus, dass ein vorhandenes Feld nie leer sein kann. Behoben. - BC/NAV: Update mit
TargetKey vom Typ Filter schlug bei Guid- oder Zahl-Schlüsseln fehl: Der Schlüssel aus KeyAttributeFromExisting wurde immer in Hochkommas gesetzt (z. B. customers('1111…')). Bei Schlüsselfeldern vom Typ Guid oder Zahl, etwa dem BC-Feld id, ergab das eine ungültige Anfrage. Der Schlüssel wird jetzt passend zum Feldtyp aus den Metadaten geschrieben, und Hochkommas im Wert werden maskiert. Fehlt das Feld im bestehenden Datensatz, bricht die Verarbeitung mit einer klaren Fehlermeldung ab statt mit einer NullReferenceException. - BC: Tabellen-Metadaten wurden zwischen API-Pfaden vermischt und nicht gefundene Tabellen dauerhaft zwischengespeichert: Der Metadaten-Cache unterschied Tabellen nur nach ihrem Namen, nicht nach dem API-Pfad. Gab es eine Tabelle (z. B.
customers) unter einem API-Pfad nicht, unter einem anderen aber schon, konnte das Ergebnis des einen Pfads für den anderen verwendet werden. War eine Tabelle beim ersten Zugriff noch nicht in $metadata enthalten (z. B. weil eine Extension erst später veröffentlicht wurde), blieb dieser Fehlschlag bis zum Neustart der Function App bestehen. Der Cache unterscheidet jetzt nach API-Pfad und Tabelle. Nicht gefundene Tabellen werden nicht mehr gespeichert, beim nächsten Aufruf wird $metadata neu gelesen. - NAV: Metadaten nicht mehr im Log, klare Fehlermeldung: Der NAV-Konnektor hat beim Laden der Metadaten die komplette
$metadata-Antwort auf Level Information geloggt. Bei echten NAV-Installationen sind das oft mehrere hundert KB bis einige MB je Neustart. Das erzeugte unnötiges Log-Volumen in Application Insights und wurde dort ohnehin abgeschnitten. Der Konnektor verhält sich jetzt wie der BC-Konnektor und loggt nur noch die Anzahl der gefundenen EntitySets. Außerdem prüft er den Statuscode. Antwortet der Server nicht mit Erfolg (z. B. 401 oder 500), erscheint Could not read Metadata from <URL> (StatusCode: …) statt eines schwer deutbaren Parse-Fehlers. Die Metadaten werden weiterhin tolerant gelesen. - NAV: Später veröffentlichte Tabellen wurden erst nach einem Neustart erkannt: Fehlte eine Tabelle beim ersten Laden der Metadaten, blieb das veraltete Modell bis zum Neustart der Function App aktiv. Jetzt werden die Metadaten beim nächsten Aufruf neu gelesen. Außerdem wird
$metadata nicht mehr doppelt abgerufen, wenn sowohl die Tabellenliste als auch die Tabellen-Metadaten benötigt werden. - Aktualisieren eines bestehenden Datensatzes in einer OpenAPI-Zielressource schlug grundsätzlich fehl: Jeder Schreibvorgang, der einen Datensatz aktualisiert statt neu anzulegen (PATCH/PUT), brach mit einer
NullReferenceException ab — betroffen war der reguläre Verarbeitungspfad ohne Antwort-Job, also der Normalfall. Ursache war eine fehlende Null-Prüfung beim Zusammenbauen des Request-Bodys. Neuanlagen (POST) waren nicht betroffen. Behoben. - OpenAPI: Aktualisieren und Löschen mit
TargetKey vom Typ Filter gingen an eine falsche URL: Der Konnektor setzte den Suchfilter selbst als Schlüssel in die Item-URL ein. Jetzt wird zuerst der passende Datensatz gesucht und dessen Schlüssel verwendet: das Feld aus KeyAttributeFromExisting, sonst der Primärschlüssel aus der Spezifikation (id, uuid …). Findet der Konnektor beim Löschen keinen Datensatz, schreibt er eine Warnung ins Log und sendet kein DELETE. Der Fehler bestand seit v2.2. - OpenAPI: Gleichnamige Ressourcen verschiedener Connections wurden vermischt: Boten zwei OpenAPI-Verbindungen eine Ressource mit demselben Namen an (z. B.
clients), verwendete die zweite das Schema der ersten. Der Fehler bestand seit v2.2. Jetzt wird das Schema je Spezifikation zwischengespeichert. - Doku OpenAPI-Konnektor korrigiert: Der Hinweis, dass der Konnektor die Spezifikation aus einer festen lokalen Datei lädt, war veraltet. Die Spezifikation wird über
openApiSpecUrl geladen. Neu dokumentiert sind zwei bekannte Einschränkungen (siehe unten).
SQL-Konnektoren (MSSQL, PostgreSQL, MySQL, Oracle)
- PostgreSQL, MySQL und Oracle als Quelle: Lesen schlug grundsätzlich fehl: Der Konnektor erzeugte eine ungültige Abfrage, weil zwischen der letzten Spalte und
FROM das Leerzeichen fehlte (z. B. …,RevenueFROM Account). Jeder Job mit einer dieser Datenbanken als Quelle brach mit einem Datenbankfehler ab (PostgreSQL: column … does not exist, MySQL: Unknown column, Oracle: ORA-00904). Der Fehler bestand seit v2.2. MSSQL war nicht betroffen. Behoben. - MSSQL: Spaltennamen werden immer in eckige Klammern gesetzt: Alle Spalten aus dem Mapping und das
WatermarkField werden jetzt in [...] eingeschlossen, nicht mehr nur Namen mit Leerzeichen. Damit funktionieren auch reservierte Wörter wie Order oder Key als Spaltenname. Für Mappings mit reinen Spaltennamen ändert sich nichts. Ausdrücke oder Aliasse als SourceField wurden schon vorher nicht unterstützt. Siehe MSSQL. - Datumsfelder aus SQL-Quellen (
DATE-Spalte) nach BC, NAV, Dataverse (CE) oder OpenAPI schlugen fehl: Stammte ein Datumswert aus einer MSSQL-, PostgreSQL-, MySQL- oder Oracle-Spalte vom Typ DATE (intern als DateOnly geführt) und das Zielfeld lag bei BC, NAV, Dataverse oder einer OpenAPI-Zielressource, brach die Verarbeitung mit Source Type not yet implemented ab. Die Datums- und Datum/Zeit-Resolver kannten nur ihren eigenen internen Typnamen „Date“, nicht „DateOnly“. Betroffen waren ausschließlich Jobs mit einer SQL-Datenbank als Quelle. Behoben, indem alle Datums-Resolver jetzt beide Typnamen akzeptieren. - Ganzzahl- und Fließkommafelder aus SQL-Quellen mit
TINYINT/SMALLINT/BIGINT/REAL schlugen fehl: Aus demselben Grund brach die Verarbeitung mit Source Type not yet implemented ab, wenn eine SQL-Spalte vom Typ TINYINT, SMALLINT, BIGINT oder einem kleinpräzisen FLOAT/REAL in ein Ganzzahl-, Dezimal- oder Fließkomma-Zielfeld bei BC, NAV oder Dataverse geschrieben wurde. Auch hier waren nur Jobs mit SQL als Quelle betroffen. Behoben. - MySQL: vorzeichenbehaftete
TINYINT-Spalten in Ganzzahlfelder: Der MySQL-Treiber liefert diese Spalten als SByte. Beim Schreiben in ein Ganzzahlfeld bei BC, NAV, Dataverse oder OpenAPI brach die Verarbeitung mit Source Type not yet implemented ab. Behoben.
Entwickler-Features
Diese Neuerungen betreffen nur die Entwicklung der DataBridge im Repository, nicht den Betrieb einer Instanz.
- Lokale Podman-Testumgebung:
dev/up.sh bzw. dev/up.ps1 startet die DataBridge aus dem aktuellen Quellcode zusammen mit Azurite und wahlweise MSSQL, PostgreSQL, MySQL und Oracle (dev/up.sh mssql oracle, dev/up.sh all). In jeder Datenbank werden dieselben Beispieltabellen Account, Opportunity und OpportunityProduct mit Testdaten angelegt, die möglichst viele Datentypen abdecken. Connections, Jobs für jede Datenbank-Kombination und Mappings werden automatisch erzeugt. Details: Entwicklung → Podman-Testumgebung. - HTTP-Mocks für Business Central, NAV und OpenAPI: Die Testumgebung kann zusätzlich einen WireMock-Container starten, der BC (OAuth), NAV (Basic) und eine OpenAPI-Beispiel-API (API-Key) nachbildet. Die Mocks sind einzeln wählbar und lassen sich mit Datenbanken mischen (
dev/up.sh mssql bc openapi, all für alles). WireMock startet nur, wenn mindestens ein Mock gewählt ist. Er lädt nur die Regeln der gewählten Mocks. Die Regeln decken den ganzen HTTP-Ablauf der Konnektoren ab: Verbindungstest, $metadata bzw. Spezifikation, Lesen mit Paging, Upsert mit Lookup, PATCH oder POST, sowie Löschen. Jeder Mock bildet jetzt alle drei Beispieltabellen ab (Account, Opportunity, OpportunityProduct — zuvor nur Account); Connections, Jobs und Mappings SQL ↔ Mock werden für alle drei automatisch angelegt. Was die DataBridge gesendet hat, zeigt das Anfrage-Protokoll unter localhost:8089/__admin/requests. Details: Entwicklung → Podman-Testumgebung. - MCP-Server
databridge-dev: Die .mcp.json enthält einen zweiten Server, der fest auf die lokale Testumgebung zeigt. So stehen in Claude Code Cloud-Instanz (databridge) und Testumgebung (databridge-dev) nebeneinander zur Verfügung. Details: Entwicklung → MCP für die Testumgebung. - Neuer Dokumentationsbereich „Entwicklung“ mit der Beschreibung beider Werkzeuge.
- Architektur im Detail: Die bisher nur intern gepflegte technische Detaildokumentation (Systemkontext, Bicep-Module, DI und
host.json, HTTP- und Nachrichten-Referenz, Sequenzdiagramme, Abhängigkeiten, Fähigkeiten-Katalog) ist überarbeitet, auf den Stand 2.3 gebracht und unter Entwicklung → Architektur im Detail veröffentlicht. Die Übersicht unter Überblick → Architektur verweist darauf. Nebenbei korrigiert: „Wie es funktioniert“ nannte einen Timer-Takt von zwei Minuten (tatsächlich 15 Sekunden) und beschrieb die Transitive-Queues als automatische Wiederholungs-Queue. - Service-Bus-Emulator, schaltbare Verarbeitung, Debug-Modus: Die Testumgebung hat jetzt einen Service-Bus-Emulator (Profil
servicebus), damit Jobs auch lokal von Anfang bis Ende laufen können. GetChanges (Timer) und Process*QueueItems lassen sich einzeln zuschalten (dev/up.sh mssql process), und dev/up.sh --host (bzw. dev\up.ps1 -HostMode) startet die Umgebung ohne den databridge-Container, damit sich ein lokal laufender Prozess mit dem Debugger daran hängen lässt. Details: Entwicklung → Podman-Testumgebung und Entwicklung → Debuggen. - Web-Oberfläche für den Service-Bus-Emulator: Läuft automatisch mit, sobald das Profil
servicebus aktiv ist (http://localhost:8090, Port über SERVICEBUS_EXPLORER_PORT konfigurierbar) — zeigt Queues, Nachrichtenzahlen und einzelne Nachrichten grafisch an. Community-Tool Service-Bus-Emulator-Explorer, nicht von Microsoft. Der klassische Service Bus Explorer funktioniert mit dem Emulator nicht. Details: Entwicklung → Debuggen → Gegen Podman. - Fix:
dev/down.sh/dev/down.ps1 ließen Service-Bus- und databridge-Container zurück. Die beiden Skripte kannten nur die Datenbank- und wiremock-Profile, nicht die seit dieser Version existierenden Profile servicebus und databridge — ein Reset (down -v) räumte deshalb servicebus, servicebus-db, servicebus-explorer und den databridge-Container nicht mit auf. Behoben, indem beide Profile in die feste Profil-Liste aufgenommen wurden. - Azurite-Connection-String direkt aus
up.sh/up.ps1: Die Start-Zusammenfassung gibt jetzt den vollständigen, einsatzbereiten Connection-String für den Azure Storage Explorer aus, statt nur UseDevelopmentStorage=true. Details zum Verbinden: Entwicklung → Podman-Testumgebung → Azurite einsehen. - Fix:
docker build aus einem frischen Checkout schlug fehl. Das Dockerfile kopierte Directory.Packages.props nicht vor dem dotnet restore-Schritt, wodurch das zentrale Paket-Versionsmanagement (ManagePackageVersionsCentrally) ins Leere lief (NU1015). Betraf nur den lokalen Container-Build (dev/up.sh/dev/up.ps1, src/compose.yml); die produktive Auslieferung baut nicht über dieses Dockerfile. Behoben. - Fix:
dev\up.ps1/dev\down.ps1 unter Windows. Nach einem podman machine stop blieb eine Socket-Datei liegen, an der beim nächsten Start win-sshproxy scheiterte. Ohne die Docker-API-Pipe brach danach jeder podman compose-Aufruf ab. Beide Skripte räumen die Datei jetzt vor dem VM-Start weg und warten, bis Compose die VM erreicht. down.ps1 -Reset startet eine gestoppte VM selbst, down.ps1 ohne -Reset endet bei gestoppter VM ohne Fehler. Unter Windows PowerShell 5.1 brach up.ps1 außerdem ab, weil Compose seinen Fortschritt auf stderr schreibt, und zeigte Umlaute verstümmelt an. Beides behoben; die Skripte laufen unter PowerShell 7 und 5.1. Details: Entwicklung → Podman-Testumgebung → Fehlersuche. - Doku-Website auf Docsy 0.18.0: Das Theme ist mit dem Umzug des Docsy-Projekts unter
github.com/docsy/docsy erreichbar; der Hugo-Modulpfad, die Mermaid-Einstellung (jetzt ein Docsy-Plugin) und Dart Sass (1.105.0) sind angepasst. Inhalt und Darstellung der Seiten bleiben gleich. - Build bricht bei NuGet-Paketen mit bekannten Sicherheitslücken ab. NuGet Audit prüft jetzt alle Projekte inklusive transitiver Pakete, und Treffer ab Schwere „moderate“ gelten als Fehler statt als Warnung („low“ bleibt eine Warnung) — lokal, im
Dockerfile und in der Pipeline. Details: Entwicklung → Architektur → Abhängigkeiten.
Bekannte Einschränkungen
- OpenAPI –
CheckList: Der Diagnose-Endpunkt meldet für OpenAPI-Mappings fälschlich „could not find table“. GetTableNames liefert die Pfade der Spezifikation (/v1/customers) statt der Ressourcennamen (customers). Das Lesen und Schreiben ist nicht betroffen. - OpenAPI – Primärschlüssel:
get_connector_table_schema weist bei OpenAPI keinen Primärschlüssel aus. Intern erkennt der Konnektor ihn weiterhin am Property-Namen. - PostgreSQL/Oracle –
CheckList: Der Diagnose-Endpunkt meldet für Mappings mit PostgreSQL- oder Oracle-Tabellen fälschlich „could not find table“. Der Vergleich der Tabellennamen berücksichtigt nicht, dass PostgreSQL Namen kleingeschrieben und Oracle großgeschrieben ablegt. Das Lesen ist nicht betroffen. - BC/NAV – Zeitstempel: In den Metadaten werden
Edm.DateTimeOffset-Felder wie lastModifiedDateTime intern mit demselben Typnamen geführt wie Edm.Date. Das betrifft nur die interne Typkennzeichnung des Quellwerts; die Uhrzeit geht dabei nachweislich nicht verloren, da die Datums-Resolver den tatsächlichen Wert unabhängig von dieser Kennzeichnung parsen.
Installationshinweise
Update von ZIP-Paket bzw. Container-Image (containered-connector:v2.3.0). Keine neuen Azure-Ressourcen. Das Bicep-Deployment setzt im schlüsselbasierten Modus zusätzlich das App-Setting TARGET_BASED_SCALING_ENABLED=0. Bei einem reinen ZIP- oder Image-Update ohne erneutes Deployment fehlt es nur, dann bleibt die Warnung im Log, die Funktion ist davon nicht betroffen.
Die Metadaten der SQL-Connectoren liefern gegenüber früheren Vorabständen teils andere Typnamen (z. B. DateOnly statt DateTime für date-Spalten). Das betrifft nur die Ausgabe von get_connector_table_schema; das Lesen von Daten ändert sich dadurch nicht.
Breaking Changes & Migrationsschritte
Verhaltensänderung bei CE-Jobs: Ist der in TargetKey verwendete Alternativschlüssel in Dataverse nicht definiert oder nicht aktiv, landen Nachrichten ab 2.3 in der Dead-Letter-Queue, statt dass der Datensatz neu angelegt wird.
- Vor dem Update für jeden CE-Zieljob mit
CustomKey prüfen, dass der Alternativschlüssel in Dataverse existiert und aktiv ist (Power Apps → Tabelle → Schlüssel, Status „Aktiv“). - Nach dem Update die Dead-Letter-Queues beobachten. Nachrichten mit einem Schlüsselfehler nach dem Aktivieren des Schlüssels erneut einreihen.
Verhaltensänderung bei CE-Zielen unter Last: Fehler beim Nachschlagen eines Zieldatensatzes (z. B. Throttling durch die Dataverse-Service-Protection-Limits) werden nicht mehr verschluckt, sondern lösen eine Wiederholung der Nachricht aus. Bei stark ausgelasteten Umgebungen können deshalb mehr Wiederholungen und, wenn die Limits länger anhalten, Einträge in der Dead-Letter-Queue auftreten — bisher wurden in diesen Fällen still falsche oder unvollständige Daten geschrieben. Diese Nachrichten nach Abklingen der Last erneut einreihen.
Managed Identity nutzen (optional)
Die Identity muss im jeweiligen Zielsystem berechtigt werden, das Bicep-Deployment erledigt das nicht:
- D365CE: Identity in der Dataverse-Umgebung als Anwendungsbenutzer anlegen und eine Sicherheitsrolle zuweisen.
- D365BC: Identity in Business Central unter Microsoft-Entra-Anwendungen anlegen, aktivieren und Berechtigungssätze zuweisen.
- Connection anpassen: für BC
"authmethod": "ManagedIdentity" setzen, für CE url statt connectionstring verwenden.
2 - Release v2.2
Neuer generischer REST/OpenAPI-Connector, ein eingebauter MCP-Server für KI-Assistenten, Action-Jobs, System-assigned Managed Identity für die Function App sowie tolerantere Behandlung leerer Schlüssel im D365CE-Upsert.
Was ist neu
Neue Funktionen
Neuer Connector: generische REST-API über OpenAPI-Spezifikation: Neben BC, CE, NAV und den SQL-Connectoren steht jetzt ein generischer HTTP-Connector zur Verfügung, der ein beliebiges REST-API anhand seiner OpenAPI-/Swagger-Beschreibung anbindet (neuer Verbindungstyp OPENAPI). Damit lassen sich Systeme ohne eigenen Connector über ihr veröffentlichtes API-Schema anbinden, statt eine dedizierte Implementierung zu benötigen. Details, Konfigurationsbeispiel und unterstützte Auth-Methoden siehe OpenAPI-Connector.
Neue Authentifizierungsart „API-Key“ für HTTP-Connectoren: Zusätzlich zu Basic-Auth und OAuth2 unterstützen alle HTTP-basierten Connectoren (BC, NAV, OpenAPI) jetzt die Authentifizierung über einen statischen API-Key, der als Header an jede Anfrage angehängt wird (apiKeyHeader / apiKeyValue in der Connection). Zusätzlich kann der OAuth2-Token-Endpunkt über tokenUrl frei konfiguriert werden, statt fest auf den Microsoft-Login-Endpunkt zu zeigen — relevant für Systeme mit eigenem oder abweichendem Token-Server.
Action-Jobs (InvokeAction): Jobs können jetzt statt eines CRUD-Datenabgleichs eine einzelne benannte Aktion auf dem Zielsystem auslösen (z. B. eine OpenAPI-Action/operationId oder einen D365CE-OrganizationRequest). Ein solcher Job benötigt kein Mapping in der Mapping-Tabelle — die Aktion und ihre Parameter werden direkt aus der Queue-Nachricht und dem Job selbst gebildet. Siehe Action — welche Änderungsarten gelesen werden.
Ressourcenpfad direkt am Job konfigurierbar: Jobs können nun ihre Quell- und Zielressource (Tabelle, Entität oder Pfad) direkt in den neuen Job-Feldern Source/Target tragen, statt sie zwingend über die Mapping-Tabelle zu beziehen. Bestehende, ausschließlich über die Mapping-Tabelle konfigurierte Jobs funktionieren unverändert weiter; ohne Eintrag in Source/Target greift wie bisher die Mapping-Tabelle.
Kind-Datensätze einbetten (EmbedChildren, D365CE): Eine neue Source-Operation erlaubt es, die Datensätze eines referenzierten Kind-Jobs (z. B. Angebotspositionen zu einem Angebot) direkt in die Queue-Nachricht des Eltern-Datensatzes einzubetten, sodass beide gemeinsam in einer Anfrage beim Ziel ankommen. Der Filter des Kind-Jobs kann dabei über {{...%parent.Feldname%...}} auf Werte des Eltern-Datensatzes zugreifen.
Neue Diagnose-Endpunkte GET /job und GET /mapping: Zwei neue, rein lesende HTTP-Endpunkte (/job, /job/{rowKey}, /mapping, /mapping/{rowKey}) geben die aktuell geladene Job- bzw. Mapping-Konfiguration zurück — praktisch zur Fehlersuche, ohne direkt in der Table-Storage nachsehen zu müssen.
Eingebauter MCP-Server für KI-Assistenten (z. B. Claude Code, GitHub Copilot, Microsoft 365 Copilot): Ein neuer, rein lesender Model-Context-Protocol-Endpunkt (POST /api/mcp) macht Jobs, Mappings sowie Service-Bus-Diagnosedaten (Queue-Laufzeit-Status, non-destruktives Peek von Nachrichten und Dead-Letter-Nachrichten) als KI-Tools ansprechbar — dediziert dafür gibt es keinen eigenen HTTP-Endpunkt. Zwei der zehn Tools gehen noch einen Schritt weiter: list_connector_tables und get_connector_table_schema lesen die echten Tabellen-/Feld-Metadaten (Typ, Nullable, maximale Länge, Primary Key) direkt aus dem Quell-/Zielsystem einer Connection — für BC, NAV, CE (Dataverse) und OpenAPI —, sodass sich ein Mapping gegen das tatsächliche Schema validieren lässt, statt sich auf die Mapping-Konfiguration allein zu verlassen. Für die SQL-Connectoren (MSSQL, MySQL, Oracle, PostgreSQL) ist das noch nicht implementiert.
Die beiden Peek-Tools geben bewusst niemals den Nachrichteninhalt zurück, nur dessen Größe in Bytes (BodySize) — der Body kann fachliche Kunden-/Geschäftsdaten des jeweiligen Jobs enthalten, die Kopf-/Fehlerdaten (JobName, ErrorMessage, Stacktrace, Zustellversuche, …) reichen für die Diagnose. Die Tool-Beschreibungen selbst sind auf Englisch verfasst, da sie vom aufrufenden KI-Modell gelesen werden, nicht von einem Menschen. Details, Einrichtung (inkl. GitHub Copilot/VS Code und Microsoft 365 Copilot Studio), die vollständige Tool-Liste mit Lese-Umfang je Tool sowie die Funktionsweise: MCP-Server.
System-assigned Managed Identity für die Function App: Die Azure Function App erhält beim Deployment automatisch eine system-zugewiesene Managed Identity. Ihre Objekt-ID (principalId) steht als Deployment-Output (functionPrincipalId) für nachgelagerte Rollenzuweisungen zur Verfügung. Die Identity wird immer angelegt.
Optional (Preview): Storage & Service Bus über Managed Identity: Über den neuen Schalter enableManagedIdentity (Standard: aus) lassen sich die Verbindungen zu Storage und Service Bus von Schlüsseln auf identitätsbasierten Zugriff umstellen. Ist der Schalter aktiv, weist das Bicep-Deployment der Identity die nötigen Rollen zu (Storage Table/Blob/Queue, Service Bus Sender/Receiver/Data Owner — Data Owner wird für die Queue-Status-Abfrage des MCP-Tools list_queue_statuses benötigt) und die App-Settings verwenden AzureWebJobsStorage__accountName bzw. …__fullyQualifiedNamespace statt der Schlüssel-Verbindungszeichenfolgen.
Standardmäßig bleibt alles beim Schlüssel-basierten Zugriff — ein reines ZIP-/Image-Update ändert daran nichts. Die Umstellung erfolgt nur, wenn das Bicep-Script mit aktiviertem Schalter neu deployt wird (siehe Installationshinweise).
Leere Quell-Schlüssel gezielt ignorieren (IgnoreEmptySourceKey, D365CE): Ist das Quellfeld eines Ziel-Schlüssels leer, brach die Verarbeitung der Nachricht bisher immer mit einem Fehler ab — auch dann, wenn ein weiterer Schlüssel den Datensatz noch hätte finden können. Mit dem neuen Feld IgnoreEmptySourceKey am TargetKey (Standard: aus) lässt sich das je Schlüssel abschalten: Der betroffene Schlüssel wird übersprungen und die Suche läuft mit dem nächsten Schlüssel nach KeyRank weiter.
Das ist vor allem im Multikey-Szenario relevant, wenn ein optionales Feld wie eine externe ID nicht in jedem Quelldatensatz gefüllt ist, ein nachrangiger Schlüssel den Zieldatensatz aber sicher findet.
Findet kein Schlüssel einen Datensatz und waren alle leer gebliebenen Schlüssel entsprechend markiert, wird ein neuer Datensatz angelegt statt ein Fehler gemeldet. War auch nur einer der leeren Schlüssel nicht markiert, bleibt es beim Fehler. Details siehe IgnoreEmptySourceKey.
Bestehende Mappings sind nicht betroffen — ohne gesetztes Feld bleibt das bisherige Verhalten unverändert.
Fehlerbehebungen & Verbesserungen
Allgemein
sample.local.settings.json war kein gültiges JSON: Eine überzählige schließende geschweifte Klammer am Dateiende hätte beim Kopieren als Vorlage für local.settings.json zu einem sofortigen JSON-Parse-Fehler geführt. Behoben.
Das in v2.1 eingeführte Grafana-Dashboard wurde zweimal überarbeitet, zunächst:
- Direkt aus der Azure Function erreichbar: Das Dashboard ist jetzt zusätzlich direkt von der Function App aus verlinkt und nicht mehr nur über die Ressourcengruppe auffindbar.
- Erfolgsraten berücksichtigen den Zeitraum: Die vier Erfolgsraten-Anzeigen (GetChanges sowie die Verarbeitung nach Priorität) werten jetzt den im Dashboard gewählten Zeitraum aus, statt einen festen Standardzeitraum zu verwenden.
- Neue Auswertung „GetChanges per Jobs": Eine zusätzliche Zeitreihe zeigt die erkannten Änderungen je Job im Zeitverlauf.
und in einem zweiten Durchgang deutlich erweitert:
- Zwei neue Custom Metrics:
MessagesProcessed (Dimensionen JobName, Outcome mit den Werten Success/Failed/Transitive) und ProcessingDurationMs (Dimension JobName) werden jetzt beim Verarbeiten jeder Queue-Nachricht getrackt — queue-übergreifend, da alle drei Prioritäts-Queues durch denselben Verarbeitungscode laufen. Details siehe Metriken. - Service-Bus-Anbindung: Zwei neue Kopfzeilen-Kacheln (Active Messages, Deadletter) zeigen die aktuell wartenden bzw. dead-letterten Nachrichten, summiert über alle drei Export-Queues — direkt aus den Azure-Monitor-Platform-Metriken des Service-Bus-Namespace, ohne eigene KQL-Abfrage.
- Kombinierte Ansicht statt drei getrennter Queue-Zeilen: Ausführungen, Laufzeiten und Job-Aufschlüsselung der Queue-Verarbeitung (
ProcessLowPriorityQueueItems/ProcessStandardQueueItems/ProcessHighPriorityQueueItems) laufen jetzt in einer gemeinsamen Zeile „ProcessQueueItems" statt in getrennten, queue-spezifischen Panels — inklusive einer neuen kombinierten Erfolgsraten-Kachel in der Kopfzeile. - Erfolg und Fehler je Job für die Queue-Verarbeitung: Zwei neue Zeitreihen-Panels („ProcessItems Success per Job", „ProcessItems Errors per Job") zeigen erfolgreiche bzw. fehlgeschlagene bzw. in eine Retry-Queue umgeleitete (
Transitive) Nachrichten aufgeschlüsselt nach Job. - Zwei neue Dashboard-Filter: Die Variable Bin Size (5 Minuten bis 1 Tag, Standard 10 Minuten) steuert die Gruppierung aller Zeitreihen-Panels; die Variable Job Namen (Mehrfachauswahl, live aus den vorhandenen Jobs ermittelt) schränkt alle job-bezogenen Panels auf die gewählten Jobs ein. Beide gelten nicht für die Kopfzeilen-Kacheln und die Exceptions-Heatmap (siehe Grafana-Dashboard für die genaue Wirkung je Panel).
- Fehler-Überblick als Heatmap: Das Exceptions-Panel wurde von einem Balkendiagramm auf eine Heatmap umgestellt.
Vollständig neu dokumentiert, inklusive der bekannten Grenzen (z. B. keine job-genaue
Erfolgsquote für GetChanges, keine Job-Filterung auf Exceptions): siehe
Grafana-Dashboard.
Das aktualisierte Dashboard wird beim nächsten Bicep-Deployment automatisch übernommen — es sind keine manuellen Schritte nötig. Neu ist dafür ein zusätzlicher Bicep-Parameter, der den Namen des Service-Bus-Namespace an das Dashboard-Modul durchreicht (serviceBusNamespaceName in modules/dashboard.bicep) — bei Deployment über die vorhandene main.bicep ist das bereits verdrahtet und erfordert keine Anpassung durch Administratoren.
D365CE (Dataverse)
- Ausweichen auf den nächsten Schlüssel funktioniert bei leeren Schlüsseln: War bei mehreren Ziel-Schlüsseln der erste in der Quelle leer, lief die anschliessende Suche im Zielsystem auf einen unbehandelten Fehler — die nachrangigen Schlüssel kamen gar nicht mehr zum Zug, obwohl sie den Datensatz gefunden hätten. Die Schlüsselsuche behandelt diesen Fall jetzt sauber und arbeitet die Schlüssel wie vorgesehen der Reihe nach ab.
SQL-Konnektoren (MSSQL, PostgreSQL, MySQL, Oracle)
Oracle- und MySQL-Konnektor: Paging funktionierte nicht: Beide Konnektoren erzeugten für jede Seite ab der zweiten eine ungültige SQL-Abfrage und brachen mit einem Datenbankfehler ab. Betroffen waren ausschließlich Tabellen, die mehr Datensätze als die konfigurierte maxPageSize je Lauf lieferten. Beide Konnektoren erzeugen jetzt dialektkorrektes Paging (Oracle: OFFSET…FETCH NEXT, MySQL: LIMIT…OFFSET).
PostgreSQL-Konnektor: Job-Filter (und damit die Watermark) wurde beim Lesen ignoriert: Der Konnektor las unabhängig vom im Job hinterlegten Filter bei jedem Lauf die komplette Tabelle neu, statt nur die seit der letzten Watermark geänderten Datensätze. Der Filter wird jetzt wie bei den übrigen SQL-Konnektoren als WHERE-Klausel übernommen.
Abbruch bei Watermark-Spalten, die kein Datum sind: War die als WatermarkField konfigurierte Spalte kein DateTime-Typ (z. B. eine fortlaufende ID oder ein rowversion-Wert), brach der Lesevorgang beim ersten Datensatz ab. Der Wert wird jetzt auch bei anderen Spaltentypen sicher verarbeitet; als Watermark-Spalte empfohlen bleibt weiterhin ein echtes Datum, da davon auch die Sortierung der Änderungen abhängt.
Installationshinweise
Dieser Abschnitt richtet sich an Administratoren, die ein bestehendes System aktualisieren.
Ein reines ZIP-/Image-Update genügt — es sind keine manuellen Konfigurationsschritte erforderlich. Die Managed Identity wird beim nächsten Bicep-Deployment automatisch angelegt.
Der neue OpenAPI-Connector, Action-Jobs, die job-eigenen Source/Target-Felder sowie EmbedChildren sind rein additiv: Bestehende Connections, Jobs und Mappings sind nicht betroffen und laufen ohne Anpassung unverändert weiter. Es sind keine neuen App-Settings und keine Bicep-Änderungen erforderlich, um die neuen Funktionen bereitzustellen — sie werden erst durch entsprechende Einträge in den Konfigurationstabellen (connections, jobs, mappings) aktiv genutzt.
Das neue Mapping-Feld IgnoreEmptySourceKey ist optional: Ohne Anpassung der Mappings bleibt das Verhalten wie bisher. Soll es genutzt werden, wird es im TargetKey-JSON der betroffenen Mapping-Zeile ergänzt ("IgnoreEmptySourceKey": true) — ein Neustart der Function App ist dafür nicht nötig, die Konfiguration wird aus dem Table Storage gelesen.
Neue Azure-Ressourcen (Bicep)
- System-assigned Managed Identity (
Microsoft.Web/sites → identity): Wird beim Deployment der Function App aktiviert (identity.type = 'SystemAssigned'). Ihre Objekt-ID wird als Deployment-Output functionPrincipalId (aus dem Modul-Output principalId) ausgegeben und dient als Grundlage für nachgelagerte Rollenzuweisungen. Es entstehen keine zusätzlichen Kosten.
Managed Identity für Storage & Service Bus aktivieren (Preview)
Optional. Nur relevant, wenn Storage und Service Bus ohne Schlüssel betrieben werden sollen.
- Schalter
enableManagedIdentity (im Marketplace-Assistenten unter Product Settings → Preview, bzw. Bicep-Parameter) auf Ja/true setzen und das Bicep-Script neu deployen. - Owner oder User Access Administrator auf der Ressourcengruppe ist dafür erforderlich, da das Deployment Rollenzuweisungen anlegt.
- Beim Deployment mit aktiviertem Schalter muss die Function-Version zur Bicep-Version passen (die neue Function-Version unterstützt beide Zugriffsarten; ältere Versionen erwarten die Schlüssel-Verbindungszeichenfolgen).
- Der
WEBSITE_CONTENTAZUREFILECONNECTIONSTRING-Content-Share bleibt weiterhin schlüsselbasiert (Azure Files unterstützt hier keine Identität). - Kurz nach der Aktivierung können durch die RBAC-Propagation vereinzelt transiente Authentifizierungsfehler auftreten; diese fangen sich beim nächsten
GetChanges-Lauf automatisch.
Container-Image
Falls die DataBridge containerisiert betrieben wird, ist das Image auf den neuen Tag zu aktualisieren:
acrwysatest.azurecr.io/containered-connector:v2.2.0
Die .NET-Basis bleibt unverändert (.NET 10, Isolated Worker) — es handelt sich lediglich um einen neuen Versions-Tag, kein Wechsel des Basis-Images.
3 - Release v2.1
Statische Schlüsselwerte, mehrere Ziel-Schlüssel, Sampling von Abhängigkeiten und ein mitgeliefertes Grafana-Dashboard.
Was ist neu
Neue Funktionen
Statische Schlüsselwerte für Lookups: Ein Lookup kann jetzt gegen einen fest hinterlegten Wert aufgelöst werden, ohne dass dafür ein Quellfeld existieren muss. Dazu wird im Schlüssel (Keyvalue) statt eines attributeName ein StaticValue angegeben. Nützlich, wenn ein Lookup immer auf denselben Zieldatensatz zeigen soll (z.B. eine feste Kategorie oder ein Standard-Datensatz).
Mehrere Ziel-Schlüssel je Mapping mit Rangfolge: Ein Table-Mapping bzw. ein Lookup kann nun mehrere Ziel-Schlüssel (TargetKeys) besitzen. Die Schlüssel werden anhand des neuen Felds KeyRank in aufsteigender Reihenfolge geprüft; sobald ein Schlüssel im Zielsystem einen Datensatz findet, wird dieser verwendet und die weiteren Schlüssel werden übersprungen. Damit lassen sich unterschiedliche Schlüssel gegen das CRM zulassen (z.B. zuerst eine externe ID, danach ersatzweise eine Nummer). Bestehende Mappings mit einem einzelnen TargetKey funktionieren unverändert weiter.
Automatische Anlage bei Lookups abschaltbar: Über die neue Option DoNotCreate am Lookup lässt sich steuern, dass ein nicht gefundener Ziel-Datensatz nicht automatisch angelegt wird. Ist die Option gesetzt, wird der Lookup nur aufgelöst, wenn der Datensatz bereits existiert — andernfalls bleibt das Feld leer, statt einen neuen Datensatz zu erzeugen.
String-zu-Decimal-Konvertierung: Der Decimal-Resolver akzeptiert jetzt auch Quellwerte vom Typ string und wandelt sie in einen Dezimalwert um (Interpretation im Format en-US, d.h. Punkt als Dezimaltrennzeichen). Leere Strings werden zu null, nicht konvertierbare Werte werfen wie bisher einen Fehler.
Vorab-Zwischenspeicherung von Lookups (Pre-Caching): Beim Verarbeiten eines Batches werden benötigte Lookup-Werte vorab gebündelt aufgelöst und zwischengespeichert. Dadurch werden wiederholte Einzelabfragen gegen das Zielsystem vermieden, was die Verarbeitung großer Änderungsmengen beschleunigt.
Sampling von Abhängigkeiten (Dependencies): Ausgehende Aufrufe an Quell- und Zielsysteme (D365 OData, SQL, Table Storage, Service Bus) werden von Application Insights automatisch als Abhängigkeiten erfasst und verursachten bisher den Großteil des Datenvolumens — bei minutengenauem Polling ein Vielfaches aller Log-Einträge zusammen. Diese Aufrufe werden nun gefiltert: Fehlgeschlagene sowie langsame Aufrufe werden immer vollständig gesendet, erfolgreiche und schnelle nur zu einem konfigurierbaren Anteil (Standard: 10 %). Das reduziert das tägliche Datenvolumen erheblich; Exceptions, Requests und alle Log-Einträge eines Fehler-Laufs bleiben unverändert vollständig erhalten. Steuerbar über die neuen Einstellungen TELEMETRY_DEPENDENCY_SAMPLE_RATE und TELEMETRY_DEPENDENCY_SLOW_MS; Details unter Betrieb → Logging.
Zu beachten
Die Entscheidung fällt pro Aufruf in dem Moment, in dem der Aufruf endet — nicht pro Funktionsausführung wie beim Logging. Ein fehlgeschlagener Lauf enthält daher zwar garantiert den fehlgeschlagenen Aufruf, nicht aber zwangsläufig die erfolgreichen Aufrufe davor. Wird dieser Verlauf für eine Analyse benötigt, ist vorübergehend TELEMETRY_CONTROL=TRACE_ALL zu setzen.
Grafana-Dashboard für Application Insights: Jede Installation legt jetzt automatisch ein vorkonfiguriertes Dashboard unter „Dashboards with Grafana" im Application-Insights-Blade an — mit Erfolgsraten je Funktion (GetChanges, Verarbeitung nach Priorität), Ausführungszahlen, Laufzeiten je Job sowie einer Übersicht der Exceptions nach Zeit und Typ. Das Dashboard wird ohne separate Aktivierung mit ausgeliefert.
Weitere Einstellungen bereits beim Deployment konfigurierbar: Der Cron-Ausdruck des GetChanges-Timers sowie alle vier Telemetrie-Sampling-Einstellungen (TELEMETRY_DEPENDENCY_SAMPLE_RATE, TELEMETRY_DEPENDENCY_SLOW_MS, TELEMETRY_INFO_SAMPLE_RATE, TELEMETRY_CONTROL) lassen sich jetzt direkt als Bicep-Parameter bzw. im Marketplace-Installationsassistenten setzen, statt sie nachträglich manuell in den App-Settings der Function App zu pflegen. Im Marketplace-Assistenten sind sie unter Product Settings in die Bereiche Function Settings, Telemetry, Alert und Preview gruppiert.
Fehlerbehebungen & Verbesserungen
Allgemein
Watermark wurde bei abweichend geschriebenem WatermarkType gelöscht: Der Typvergleich war zeichengenau. Ein in der Tabelle jobs von Hand eingetragenes DateTime statt datetime (oder ein versehentliches Leerzeichen) führte dazu, dass die gespeicherte Watermark des Jobs geleert wurde. Da die DataBridge bei leerer Watermark den Filter-Block vollständig entfernt, las der betroffene Job anschließend das komplette Quellsystem — und zwar bei jedem Lauf erneut, ohne Fehlermeldung oder Warnung. Der Typ wird nun ohne Beachtung von Groß-/Kleinschreibung und ohne umgebende Leerzeichen erkannt; ein tatsächlich unbekannter Typ lässt die gespeicherte Watermark unangetastet und erzeugt eine Warnung im Log. Siehe Installationshinweise — betroffene Jobs sollten nach dem Update geprüft werden.
Deutlich weniger Zugriffe auf die Watermark-Tabelle: Die Prüfung, welche Jobs laut Zeitplan fällig sind, holte für jeden aktiven Job eine eigene Abfrage aus der Tabelle watermark, obwohl dafür nur ein Zeitstempel benötigt wird. Diese Einzelabfragen sind durch eine gebündelte Abfrage ersetzt. Bei rund 220 aktiven Jobs sinkt die Zahl der Lesezugriffe von ~7.400 auf ~810 pro Stunde. Die Anzahl der Schreibzugriffe bleibt unverändert. Das entlastet Azure Table Storage und reduziert zusätzlich das Datenvolumen in Application Insights.
Watermark-Vergleich robuster: Drei Detailprobleme in der Watermark-Auswertung wurden behoben. Zeitstempel werden nun zeitzonenunabhängig verglichen — bisher wurde die Zeitangabe in die lokale Zeit des Servers umgerechnet, was beim Typ date über eine Tagesgrenze springen und das Vergleichsergebnis je nach Betriebsstandort verändern konnte. Fehlt ein Änderungsmarker, bleibt die Watermark unverändert stehen statt einen Abbruch auszulösen. Und eine fehlende Watermark-Spalte in der Tabelle führt nicht mehr zu einem leeren Rückschreibewert.
Validate-Funktion auf async umgestellt: Die Diagnose-Funktion Validate verwendete synchrone I/O (WriteString) sowie ein blockierendes .Wait()/.Result beim Warten auf die Initialisierung — beides ist mit dem ASP.NET Core-Modus nicht kompatibel. Sie ist jetzt vollständig auf async/await umgestellt.
Aussagekräftigeres Logging bei ExecuteHttpRequest: Bei ad-hoc HTTP-Anfragen werden jetzt der HTTP-Statuscode und der Antwortinhalt getrennt protokolliert, was die Fehlersuche bei fehlgeschlagenen Requests erleichtert.
Erweiterte Auswertungs-Abfragen für Abhängigkeiten und Kosten: Die Dokumentation enthält neue KQL-Abfragen für die langsamsten Abhängigkeiten, fehlgeschlagene Aufrufe nach Zielsystem sowie eine Volumenanalyse pro Tabelle zur Ursachensuche bei erreichter Daten-Obergrenze (Daily Cap). Siehe Betrieb → Logging.
BC & NAV
Statische Schlüsselwerte im BcConnector-Filter: Die Schlüssel- und Filtererzeugung des Business-Central-Connectors berücksichtigt nun ebenfalls statische Schlüsselwerte (StaticValue), sodass die neuen Lookup-Funktionen auch gegen D365 BC funktionieren. Zusätzlich wurde ein Fehler behoben, durch den Schlüsselwerte vom Typ string (z.B. Nummernfelder) ohne umschließende Anführungszeichen in den OData-Filter geschrieben wurden — ein mehrteiliger Schlüssel mit einem String-Anteil führte dadurch zu einer ungültigen Filterabfrage gegen BC. Der Filter wird nun für string-Werte korrekt in Anführungszeichen gesetzt.
Korrekte Fehlermeldung im NavConnector: Eine Fehlermeldung im NAV-Connector verwies fälschlich auf „BC-Communication" — sie lautet jetzt korrekt „NAV-Communication".
Installationshinweise
Ein Update auf v2.1 erfordert keine zwingenden Konfigurationsänderungen. Die neuen Mapping-Funktionen (statische Schlüsselwerte, mehrere Ziel-Schlüssel, DoNotCreate) werden ausschließlich über die Mapping-Konfiguration in Azure Table Storage aktiviert und sind für bestehende Mappings optional — ohne Konfigurationsänderung bleibt das bisherige Verhalten erhalten.
Empfohlen wird jedoch eine einmalige Sichtprüfung der Tabelle jobs (siehe unten) — sie deckt eine Fehlkonfiguration auf, die bisher unbemerkt zu Vollabzügen geführt haben kann.
Neue / geänderte App-Settings (Azure Function)
Beide Einstellungen sind optional. Ohne Konfiguration gelten die angegebenen Standardwerte, das Sampling von Abhängigkeiten ist also ab dem Update automatisch aktiv.
| Einstellung | Typ | Standard | Beschreibung | Pflicht |
|---|
TELEMETRY_DEPENDENCY_SAMPLE_RATE | Integer (0–100) | 10 | Prozentualer Anteil der erfolgreichen und schnellen Abhängigkeits-Aufrufe, die an App Insights gesendet werden. Fehlgeschlagene und langsame Aufrufe sind davon nicht betroffen. | Nein |
TELEMETRY_DEPENDENCY_SLOW_MS | Integer (ms) | 2000 | Schwellwert, ab dem ein Aufruf als „langsam" gilt und immer gesendet wird — auch bei Erfolg. | Nein |
Die bestehende Einstellung TELEMETRY_CONTROL wirkt nun zusätzlich auf Abhängigkeiten: TRACE_ALL deaktiviert auch deren Sampling, TRACE_NONE unterdrückt sie vollständig.
Diese beiden sowie die bereits bestehenden Einstellungen TELEMETRY_INFO_SAMPLE_RATE, TELEMETRY_CONTROL und GetChangesTimerExpression lassen sich ab dieser Version zusätzlich direkt beim Deployment setzen — als Bicep-Parameter (Beispielwerte in bicep/params/databridge.sample.bicepparam) oder im Marketplace-Assistenten unter Product Settings. Bei einem Update per Marketplace-Assistent führt ein erneuter Durchlauf zu keiner Änderung, solange die Standardwerte übernommen werden.
Neue Azure-Ressourcen (Bicep)
- Grafana-Dashboard (
Microsoft.Dashboard/dashboards + dashboardDefinitions): Vorkonfiguriertes Dashboard in Application Insights („Dashboards with Grafana"). Wird bei jedem Deployment fest mit angelegt, ohne Opt-out-Möglichkeit. Verursacht keine zusätzlichen Kosten; Abfragen laufen gegen die bestehende Application-Insights-Instanz.
Zu prüfen nach dem Update: WatermarkType in der Tabelle jobs
Die Tabelle jobs ist einmalig daraufhin durchzusehen, ob im Feld WatermarkType ein abweichend geschriebener Wert steht — erwartet werden datetime oder string. Abweichungen wie DateTime, Datetime oder ein führendes Leerzeichen haben bis einschließlich der Vorversion dazu geführt, dass der betroffene Job seine Watermark verlor und bei jedem Lauf das komplette Quellsystem las.
Nach dem Update ist der Fall auch ohne Prüfung erkennbar: Ein nicht erkannter Typ erzeugt eine Warnung mit Jobnamen und dem hinterlegten Rohwert im Log.
Was bei einem betroffenen Job zu erwarten ist: Ist die Watermark bereits geleert, führt der erste Lauf nach dem Update noch einmal einen Vollabzug durch. Danach wird die Watermark korrekt fortgeschrieben und der Job arbeitet wieder inkrementell. Es ist also kein manueller Eingriff nötig — lediglich einmalig mit erhöhter Last für diesen Job zu rechnen.
Hinweis zu bestehenden Auswertungen
Verworfene Abhängigkeiten werden vollständig entfernt und nicht über einen Hochrechnungsfaktor (itemCount) kompensiert. Bestehende Dashboards, Alerts oder KQL-Abfragen, die auf absoluten Zählungen oder Durchschnittslaufzeiten der Tabelle dependencies / AppDependencies basieren, liefern nach dem Update zu niedrige Werte und sind zu prüfen.
Besonders zu beachten sind Fehlerquoten über die Tabelle dependencies: Da fehlgeschlagene Aufrufe vollständig erhalten bleiben, erfolgreiche aber gesampelt werden, ist ein Ausdruck der Form countif(success == false) / count() nach dem Update deutlich überhöht. Solche Abfragen und darauf basierende Alerts sind zu entfernen oder auf die requests-Tabelle umzustellen, die keinem Sampling unterliegt.
Nicht betroffen sind:
- Fehleranzahlen und Fehlerursachen — fehlgeschlagene Aufrufe werden nie verworfen
- Auswertungen langsamer Aufrufe — diese werden ab dem Schwellwert immer gesendet
- Requests, Exceptions, Traces und Custom Metrics — unverändert
Für belastbare Mengenangaben sind die vorab aggregierten Custom Metrics zu verwenden, die keinem Sampling unterliegen.
Container-Image
Falls die DataBridge containerisiert betrieben wird, ist das Image auf den neuen Tag zu aktualisieren:
acrwysatest.azurecr.io/containered-connector:v2.1.0
Die .NET-Basis bleibt unverändert (.NET 10, Isolated Worker) — es handelt sich lediglich um einen neuen Versions-Tag, kein Wechsel des Basis-Images.
4 - Release v2.0
Umstellung auf .NET 10, Containerisierung mit Docker Compose, gepuffertes Logging und Custom Metrics.
Was ist neu
Neue Funktionen
Containerisierung mit Docker Compose: Die DataBridge kann nun direkt über docker compose (bzw. Podman) lokal gestartet werden. Eine neue compose.yml sowie eine Beispiel-Umgebungsdatei (.podman/podman.env.sample) sind enthalten. Das Start-Skript start-local.sh / start-local.ps1 baut den Container, startet ihn und gibt alle HTTP-Trigger-URLs inkl. Authentication-Key direkt aus.
Robustere Initialisierung in GetChanges: Die Timer-Funktion GetChanges initialisiert den CoreService jetzt threadsicher (Mutex-Pattern). Schlägt die Initialisierung fehl, wird sie beim nächsten Timer-Durchlauf automatisch erneut versucht (Self-Repair) — analog zu ProcessQueueItems.
ASP.NET Core HTTP-Integration: Die Azure Functions App nutzt nun das ASP.NET Core-Integrationsmodell (ConfigureFunctionsWebApplication). Dies ist die empfohlene Methode ab .NET 8+ und ermöglicht vollständigere HTTP-Features.
Custom Metrics: Die DataBridge sendet eigene, pre-aggregierte Metriken an Application Insights (Namespace DataBridge). Erste Metrik: ChangesDetected mit Dimension JobName — Anzahl erkannter Änderungen pro Job und GetChanges-Lauf, inkl. Null-Werten. Sichtbar im Metrics Explorer und in der Tabelle customMetrics; Details unter Betrieb → Logging.
Gepuffertes Logging mit selektiver App-Insights-Weiterleitung: Alle Log-Einträge einer Funktionsausführung werden zunächst im Arbeitsspeicher gepuffert und erst am Ende der Ausführung — abhängig vom Ergebnis — selektiv an Azure Application Insights gesendet. Im Fehlerfall stehen damit auch alle Debug-Einträge rückwirkend zur Verfügung, ohne dass sie bei erfolgreichen Läufen Kosten verursachen. Das Verhalten lässt sich über die Umgebungsvariablen TELEMETRY_CONTROL und TELEMETRY_INFO_SAMPLE_RATE steuern. Eine vollständige Beschreibung befindet sich unter Betrieb → Logging.
Trace-Level für Live-Diagnose: Log-Einträge auf Level Trace (LogTrace) werden nie an Application Insights gesendet — auch nicht bei Fehler-Läufen. Sie sind ausschließlich live sichtbar: lokal in der Konsole bzw. im Container-Log, in Azure im Log Stream der Function App. Details unter Betrieb → Logging.
Fehlerbehebungen & Verbesserungen
Allgemein
Korrekte Zeitstempel und Request-Zuordnung für gepufferte Traces: Gepufferte Log-Einträge tragen in Application Insights jetzt den Zeitpunkt des ursprünglichen Log-Aufrufs statt des Sendens am Invocation-Ende. Zusätzlich wird operation_ParentId gesetzt, sodass Traces in der End-to-End-Transaktionsansicht korrekt unter dem Request der Invocation eingeordnet werden statt als verwaiste Einträge zu erscheinen.
CheckList erkennt _-Felder korrekt: Die Diagnose-Funktion CheckList hat _-präfixierte Source-Felder (z.B. _wysa_address1_countryid) fälschlich als fehlende Attribute gemeldet. Diese Felder werden zur Laufzeit über SourceOperations aufgelöst und sind keine direkten Connector-Attribute — sie werden nun korrekt übersprungen.
HTTP-Funktionen auf async umgestellt: GetInfo, CheckList und ExecuteHttpRequest verwendeten synchrone I/O-Operationen (WriteString, .Wait()), die mit dem ASP.NET Core-Modus nicht kompatibel sind. Alle drei Funktionen sind jetzt vollständig auf async/await umgestellt.
Blockierendes Initialisierungsproblem in GetChanges behoben: Die bisherige Initialisierung blockierte den Thread (.Wait()). Dies wurde auf async/await umgestellt, womit Deadlocks unter Last verhindert werden.
Versionsverwaltung in der Pipeline zentralisiert: Major- und Minor-Version (2.0) werden nun zentral in der Pipeline-Datei gepflegt statt verteilt in den Build-Templates.
Automatischer Pipeline-Trigger: Die Build-Pipeline startet jetzt automatisch bei Push auf main und preview (vorher: nur manuell auslösbar).
Global-Artifact-Veröffentlichung nur von main: Das NuGet-Paket dsyr-databridge wird nur noch beim Build aus dem main-Branch veröffentlicht, nicht mehr aus preview.
NuGet-Pakete aktualisiert: Alle Abhängigkeiten wurden auf aktuelle Versionen angehoben (u.a. Azure.Identity 1.21, Microsoft.Data.SqlClient 7.0, MySql.Data 9.7, Npgsql 10.0.2, Oracle.ManagedDataAccess.Core 23.26.200).
Veraltete ARM-Templates entfernt: Legacy-ARM-Deployment-Profile und veraltete AppInsights-ARM-Dateien wurden aus dem Repository entfernt.
Docker-Build-Kontext bereinigt: Das .dockerignore wurde erweitert, sodass nur noch der tatsächlich benötigte Anwendungscode ins Image gelangt (.git/, docfx/, bicep/, cicd/, bruno/ und lokale Start-Scripts werden nun explizit ausgeschlossen).
BC
- Duplikate bei HTTP-Fehlern verhindert: Beim Nachschlagen von Datensätzen (
RetrieveRecordByKey, RetrieveRecordByFilter) wurde bei unerwarteten HTTP-Statuscodes bisher stillschweigend null zurückgegeben — das System legte daraufhin fälschlich einen neuen Datensatz an und erzeugte Duplikate. Beide Methoden werfen jetzt eine Exception mit dem konkreten Statuscode, wenn der Server weder Erfolg noch 404 zurückliefert.
Installationshinweise
Neue / geänderte App-Settings (Azure Function)
Folgende neue App-Settings stehen zur Verfügung. Beide sind optional — ohne Konfiguration gelten die dokumentierten Standardwerte.
| Setting | Typ | Standard | Beschreibung |
|---|
TELEMETRY_CONTROL | String | (leer) | TRACE_ALL sendet alle Log-Einträge unabhängig vom Ergebnis; TRACE_NONE unterdrückt alle Einträge; TRACE_SAMPLE entspricht dem Standardverhalten (selektives Sampling, wie leer) |
TELEMETRY_INFO_SAMPLE_RATE | Integer (0–100) | 20 | Prozentsatz der Information-Einträge, die bei erfolgreichen Läufen an App Insights gesendet werden |
Neue Azure-Ressourcen (Bicep)
Es wurden keine neuen Azure-Ressourcen hinzugefügt.
Breaking Changes & Migrationsschritte
Laufzeitversion auf .NET 10 aktualisieren
Die Azure Function App muss auf .NET 10 (Isolated Worker) aktualisiert werden.
Im Azure Portal: Function App → Konfiguration → Allgemeine Einstellungen → .NET-Version → 10 (LTS, Isolated)
Im Bicep-Script wird netFrameworkVersion automatisch auf 10.0 gesetzt — ein Redeployment über die Pipeline genügt.
Container-Image aktualisieren
Falls die DataBridge containerisiert betrieben wird: Das neue Image basiert auf .NET 10.
Tag: acrwysatest.azurecr.io/containered-connector:v2.0.0
Bestehende Images auf .NET 8 Basis sind nicht kompatibel und müssen ersetzt werden.
Build-Agent in eigenen Pipelines prüfen
Die offizielle Pipeline nutzt jetzt windows-2025 als Build-Agent. Eigene abgeleitete Pipelines sollten entsprechend angepasst werden.
5 - Ältere Releases
Migrationshinweise für die Übergänge 1.0 → 1.1 und 1.1 → 2.0.
Für die Versionen vor 2.0 existiert keine vollständige Release-Dokumentation. Überliefert
sind die Breaking Changes der jeweiligen Übergänge — sie sind hier unverändert festgehalten,
damit die Migrationshistorie nicht verloren geht.
Vor der Migration lesen
Wer von einer Version vor 2.0 aktualisiert, muss die Schritte aller dazwischenliegenden
Übergänge nacheinander durchführen — zusätzlich zu den Installationshinweisen aus
v2.0 und v2.1.
1.0 → 1.1
Breaking Changes:
- Einführung von vier neuen Service-Bus-Warteschlangen:
sbqignored, sbqtransitivestandart, sbqtransitivelow, sbqtransitivehigh - Einführung der neuen Anwendungseinstellung
SkipOutdatedMessages in der Azure Function;
beim Upgrade von 1.0 auf false zu setzen
Schreibweise der Queue-Namen
Der Name sbqtransitivestandart ist im Produkt genau so geschrieben (mit t am Ende)
und darf beim Anlegen der Warteschlange nicht „korrigiert" werden — sonst findet die
DataBridge die Queue nicht.
1.1 → 2.0
Breaking Change:
Die vollständigen Migrationsschritte für diesen Übergang stehen in den
Installationshinweisen zu v2.0.