Mappings (mappings)

Die mappings-Tabelle definiert, welche Felder wie zwischen Quell- und Zielsystem übertragen und transformiert werden.

Die mappings-Tabelle ist die mächtigste Konfigurationsebene der DataBridge. Sie legt für jedes Feld fest: woher kommt der Wert, wohin geht er, und wie wird er unterwegs transformiert.

Ein Mapping ist eine Gruppe von Zeilen in der Tabelle — alle mit demselben PartitionKey. Jede Zeile beschreibt genau eine Feld-Zuordnung.


Tabellenstruktur

SpaltePflichtBeschreibung
PartitionKey✅Name des Mappings. Wird im Job unter Mapping referenziert. Im Gegensatz zu jobs und connections ist der PartitionKey hier frei wählbar — er dient der Gruppierung.
RowKey✅Eindeutiger Bezeichner innerhalb des Mappings. Konvention: _quellfeld__zielfeld_
SourceTable✅Name der Quelltabelle/-entität. Muss innerhalb eines Mappings konsistent sein.
SourceField—Name des Quellfeldes. Kann leer sein (bei DefaultValue) oder mit _ beginnen — dann handelt es sich um ein virtuelles Feld.
TargetTable✅Name der Zieltabelle/-entität. Muss innerhalb eines Mappings konsistent sein.
TargetField✅Name des Zielfeldes. Muss dem tatsächlichen API-/Spaltenname entsprechen.
TargetKey—JSON-Objekt. Definiert, wie ein bestehender Datensatz im Zielsystem identifiziert wird (für Upsert-Logik).
SourceOperation—JSON-Objekt der Form { "Operations": [ … ] }. Transformation beim Lesen aus der Quelle.
TargetOperation—JSON-Objekt der Form { "Operations": [ … ] }. Transformationen beim Schreiben ins Ziel.

RowKey-Namenskonvention

Die empfohlene Konvention für den RowKey: _quellfeld__zielfeld_

Beispiele:

_systemid__wysa_bcsystemid_
_lastModifiedDateTime__wysa_lastmodified_
_no__wysa_bcnumber_

Doppelter Unterstrich trennt Quell- vom Zielfeld. Die umgebenden Unterstriche kennzeichnen es als Mapping-RowKey. Diese Konvention ist optional, aber empfohlen für Lesbarkeit und Filterbarkeit.


TargetKey — Upsert-Schlüssel

Der TargetKey bestimmt, wie die DataBridge entscheidet, ob ein Datensatz im Zielsystem angelegt (Insert) oder aktualisiert (Update) wird.

Es gibt vier Typen:

PrimaryKey

Nutzt den systemnativen Primärschlüssel des Zielsystems. Der Schlüsselname wird automatisch aus dem SourceField der Mapping-Zeile übernommen.

{ "KeyType": "PrimaryKey" }

Id

Ähnlich wie PrimaryKey, nutzt jedoch die systemspezifische ID-Eigenschaft des Connectors.

{ "KeyType": "Id" }

CustomKey

Benutzerdefinierter Schlüssel aus einem oder mehreren Feldern. Wird eingesetzt, wenn der Datensatz im Zielsystem nicht über den Primärschlüssel, sondern über eine Geschäftsfeld-Kombination identifiziert wird.

{
  "KeyType": "CustomKey",
  "KeyName": "wysa_number",
  "KeyValues": [
    { "keyName": "wysa_segmentno", "attributeName": "segmentNo", "rank": 1 },
    { "keyName": "wysa_lineno",    "attributeName": "lineNo",    "rank": 2 }
  ]
}
FeldBedeutung bei CustomKey
KeyNameZielfeld, das den zusammengesetzten Schlüsselwert enthält
keyNameZielfeld-Name für diesen Schlüsselteil
attributeNameQuellfeld-Name, aus dem der Wert kommt
StaticValueFester Wert statt eines Quellwertes (siehe unten)
rankReihenfolge der Schlüsselteile innerhalb des Schlüssels (aufsteigend)

Filter

Sucht im Zielsystem nach einem Datensatz, der alle angegebenen Feld-Wert-Kombinationen erfüllt. Im Gegensatz zu CustomKey wird kein explizites Schlüsselfeld benötigt.

{
  "KeyType": "Filter",
  "KeyValues": [
    { "keyName": "mailingGroupCode", "attributeName": "listid",   "rank": 1 },
    { "keyName": "contactNo",        "attributeName": "entityid", "rank": 2 }
  ]
}

Statische Schlüsselwerte

(ab v2.1 — verfügbar für D365CE und D365BC)

Ein Schlüsselteil kann gegen einen fest hinterlegten Wert aufgelöst werden, ohne dass dafür ein Quellfeld existieren muss. Dazu wird statt attributeName das Feld StaticValue gesetzt:

{
  "KeyType": "CustomKey",
  "KeyName": "wysa_category",
  "KeyValues": [
    { "keyName": "wysa_category", "StaticValue": "STANDARD", "rank": 1 }
  ]
}

StaticValue greift nur, wenn attributeName leer ist. Ist beides gesetzt, gewinnt der Quellwert.

Bei Business Central werden statische Werte für die Metadaten-Typen string, guid und int32 unterstützt; andere Typen führen zu einem Fehler.

Mehrere Ziel-Schlüssel mit Rangfolge

(ab v2.1)

Ein Mapping kann mehrere Ziel-Schlüssel besitzen. Sie werden anhand des Feldes KeyRank in aufsteigender Reihenfolge geprüft — sobald ein Schlüssel im Zielsystem einen Datensatz findet, wird dieser verwendet und die übrigen werden übersprungen.

Typischer Einsatz: zuerst über eine externe ID suchen, ersatzweise über eine Nummer.

Die Konfiguration unterscheidet sich je nach Ebene:

EbeneVorgehen
Table-MappingJe Schlüssel eine eigene Mapping-Zeile mit eigenem TargetKey-JSON anlegen. Die DataBridge fasst alle TargetKey-Einträge einer Mapping-Gruppe zusammen und sortiert sie nach KeyRank.
Lookup (TargetOperation)In Parameters statt TargetKey ein Array TargetKeys mit mehreren Schlüsseln angeben.
{
  "KeyType": "CustomKey",
  "KeyRank": 1,
  "KeyName": "wysa_externalid",
  "KeyValues": [
    { "keyName": "wysa_externalid", "attributeName": "externalId", "rank": 1 }
  ]
}

Bestehende Mappings mit einem einzelnen TargetKey funktionieren unverändert — intern wird ein einzelner Schlüssel wie eine Liste mit einem Eintrag behandelt.

KeyAttributeFromExisting

Optionales Feld am TargetKey. Wird von den Konnektoren für Business Central und NAV ausgewertet, um beim Aktualisieren ein Schlüsselattribut aus dem bereits vorhandenen Zieldatensatz zu übernehmen.

IgnoreEmptySourceKey

(ab v2.2, nur D365CE)

Optionales Boolesches Feld am TargetKey. Standard ist false.

{
  "KeyType": "CustomKey",
  "KeyRank": 2,
  "KeyName": "wysa_externalid",
  "IgnoreEmptySourceKey": true,
  "KeyValues": [
    { "keyName": "wysa_externalid", "attributeName": "externalId", "rank": 1 }
  ]
}

Zwei verschiedene Arten von „kein Treffer"

Um das Feld einordnen zu können, muss man zwei Situationen auseinanderhalten, die beide danach aussehen, als wäre ein Schlüssel erfolglos geblieben:

SituationWas passiertVerhalten ohne dieses Feld
Schlüssel lässt sich nicht aufbauen — das Quellfeld ist leer, es gibt gar keinen Wert zum SuchenEs wird nicht gesuchtFehler, die Nachricht schlägt fehl
Schlüssel findet nichts — es wurde gesucht, im Zielsystem existiert der Datensatz noch nichtSuche läuft, bleibt ergebnislosDatensatz wird angelegt — kein Fehler

Die zweite Zeile ist der Normalfall für jeden neuen Datensatz: Beim ersten Übertragen findet kein Schlüssel etwas, und genau deshalb wird angelegt. IgnoreEmptySourceKey ändert daran nichts.

Das Feld wirkt ausschliesslich auf die erste Zeile: Es erklärt einen leeren Quellwert für diesen einen Schlüssel zum Normalfall statt zum Fehler.

Wann das Feld überhaupt zum Tragen kommt

Die Schlüssel werden nach KeyRank der Reihe nach geprüft. Sobald ein Schlüssel einen Datensatz findet, bricht die Suche ab und der Datensatz wird aktualisiert — unabhängig davon, was bei den vorherigen Schlüsseln passiert ist und wie sie konfiguriert sind.

Beispiel mit drei Schlüsseln, bei dem Schlüssel 1 leer und nicht markiert ist:

SchrittErgebnis
Schlüssel 1leer, wird übersprungen — gemerkt: „hier war ein Fehler"
Schlüssel 2leer, markiert — wird übersprungen
Schlüssel 3findet den Datensatz → Suche endet
ErgebnisUpdate. Kein Fehler — der gemerkte Fehler wird gar nicht mehr ausgewertet

Das Feld greift also nur dann, wenn die Liste vollständig durchlaufen wurde und kein einziger Schlüssel einen Datensatz gefunden hat. Erst dann steht die Frage „Fehler oder anlegen?" überhaupt im Raum.

Die Entscheidung am Ende

Hat kein Schlüssel etwas gefunden, entscheidet sich Folgendes:

  • Waren alle leer gebliebenen Schlüssel mit IgnoreEmptySourceKey: true markiert (oder blieb gar keiner leer), wird ein neuer Datensatz angelegt.
  • War auch nur einer der leer gebliebenen Schlüssel nicht markiert, bleibt es beim Fehler.

Das Feld gilt also je Schlüssel: Es hebt die Fehlerbehandlung der übrigen Schlüssel nicht auf. Lassen Sie es bei einem Schlüssel bewusst weg, bleibt ein leerer Wert dort ein Fehler — auch wenn ein anderer Schlüssel des Mappings markiert ist.

Typischer Einsatz

Ein optionales Feld wie eine externe ID ist nicht in jedem Quelldatensatz gefüllt, die Belegnummer dagegen immer. Mit IgnoreEmptySourceKey: true am ID-Schlüssel laufen auch die Datensätze ohne externe ID sauber durch und werden über die Belegnummer gefunden.

Das Feld wird derzeit ausschliesslich vom D365CE-Konnektor ausgewertet. Bei Business Central und NAV bleibt es wirkungslos.


Virtuelle Felder

Beginnt das SourceField mit einem Unterstrich, handelt es sich um ein virtuelles Feld: Es wird nicht aus der Quelltabelle gelesen, sondern zur Laufzeit über eine SourceOperation erzeugt.

Der ResponseJob ist dabei nur einer von mehreren Anwendungsfällen:

AnwendungsfallOperation
Wert aus einer anderen Tabelle nachschlagenLookupValue
Wert aus einer ActivityParty-Beziehung lesenActivityParty
Link auf einen Dataverse-Datensatz erzeugenLinkToRecord
Wert aus der Antwortnachricht lesen (ResponseJob)ReadFromMessage
Zeilen eines Kind-Jobs einbettenEmbedChildren

SourceOperation — Transformation beim Lesen

SourceOperations werden angewendet, bevor der Wert in die Service Bus Queue geschrieben wird. Sie sind connector-spezifisch — nicht jede Operation steht in jedem Connector zur Verfügung.

LookupValue

(verfügbar: D365BC, D365CE, D365NAV)

Liest einen Wert aus einer anderen Tabelle im Quellsystem nach. Beispiel: Aus einem Land-Code soll der ausgeschriebene Ländername übertragen werden.

{
  "Operations": [
    {
      "Name": "LookupValue",
      "Parameters": {
        "LookupType": "Attribute",
        "SourceField": "countryRegionCode",
        "LookupTable": "publisher/product/v1.0/countriesRegions",
        "LookupField": "name",
        "UseCache": true
      }
    }
  ]
}
ParameterBeschreibung
LookupTypeAttribute — liest ein bestimmtes Feld aus dem gefundenen Datensatz. Name — liefert den Anzeigenamen des verknüpften Datensatzes; dann entfallen LookupTable und LookupField.
SourceFieldFeld im Quelldatensatz, das den Suchwert enthält
LookupTableAPI-Pfad der nachzuschlagenden Tabelle
LookupFieldFeld im nachgeschlagenen Datensatz, dessen Wert übertragen wird
UseCachetrue dringend empfohlen — siehe Hinweis

ReadFromMessage

(verfügbar: D365BC, D365NAV, D365CE)

Liest einen Wert aus der ursprünglichen Queue-Nachricht — wird typischerweise in ResponseJobs verwendet, um Felder aus der Antwort des Zielsystems (z. B. eine neu vergebene ID) zurückzuschreiben.

{
  "Operations": [
    { "Name": "ReadFromMessage" }
  ]
}

Zugehörige Zeile in der Tabelle:

SpalteWert
SourceField_id (Unterstrich-Präfix!)
TargetFieldwysa_bcid

ActivityParty

(verfügbar: nur D365CE)

Liest ein Feld über eine ActivityParty-Beziehung aus. Wird für CE-Aktivitäten (E-Mails, Aufgaben) verwendet, bei denen Teilnehmer über den activityparty-Datensatz verknüpft sind.

{
  "Operations": [
    {
      "Name": "ActivityParty",
      "Parameters": {
        "PartyParams": {
          "TypeMask": 2,
          "SourceField": "activityid",
          "TargetField": "wysa_number",
          "TargetTable": "contact"
        }
      }
    }
  ]
}
ParameterBeschreibung
TypeMaskTeilnehmertyp (siehe Hinweis)
SourceFieldFeld mit der Activity-ID
TargetFieldFeld im verknüpften Datensatz, das gelesen werden soll
TargetTableEntität des verknüpften Datensatzes

Werden mehrere Teilnehmer gefunden, werden ihre Werte komma-separiert zusammengefügt.

LinkToRecord

(verfügbar: nur D365CE)

Erzeugt eine anklickbare URL zu einem Datensatz in Dataverse. Nützlich, um in BC oder SQL einen direkten Link auf den zugehörigen CE-Datensatz zu speichern.

{
  "Operations": [
    {
      "Name": "LinkToRecord",
      "Parameters": {
        "BaseUrl": "https://<org>.crm4.dynamics.com/main.aspx?appid=<AppId>&pagetype=entityrecord"
      }
    }
  ]
}

An die angegebene Basis-URL werden automatisch &etn=<entity> und &id=<guid> angehängt.

EmbedChildren

(neu, verfügbar: nur D365CE als Quellsystem)

Bettet die Zeilen eines referenzierten Kind-Jobs in die Nachricht des Elterndatensatzes ein, sodass Eltern- und Kind-Datensätze gemeinsam als eine Nachricht durch den Service Bus laufen und gemeinsam ins Ziel geschrieben werden — z. B. eine Rechnung mit ihren Rechnungspositionen.

{
  "Operations": [
    {
      "Name": "EmbedChildren",
      "Parameters": { "JobName": "invoice-lines" }
    }
  ]
}

Zugehörige Zeile in der Tabelle:

SpalteWert
SourceField_lines (Unterstrich-Präfix, beliebiger Name)
TargetFieldPfad im Zieldatensatz, unter dem das Array landet (z. B. lines)

Der referenzierte Kind-Job liefert SourceConnection, Quellressource und Mapping; sein Filter kann {{...%parent.feld%...}}-Platzhalter enthalten, die zur Abrufzeit gegen den Eltern-Quelldatensatz aufgelöst werden. Beim Schreiben in eine OpenAPI-Zielressource wird daraus ein verschachteltes JSON-Array gebaut und unverändert — ohne Feld-für-Feld-Abgleich gegen ein eventuell vorhandenes Zielarray — mit der Elternanfrage übertragen.


TargetOperation — Transformationen beim Schreiben

TargetOperations werden angewendet, bevor der Wert ins Zielsystem geschrieben wird.

DefaultValue

(alle Konnektoren)

Schreibt immer einen festen Wert ins Zielfeld — unabhängig vom Quellwert. Das SourceField kann in diesem Fall leer gelassen werden.

{
  "Operations": [
    { "Name": "DefaultValue", "Parameters": { "DefaultValue": "2" } }
  ]
}

DefaultValueIfNullOrEmpty

(alle Konnektoren)

Schreibt einen festen Wert nur dann, wenn das Quellfeld leer oder null ist. Ist ein Quellwert vorhanden, wird dieser unverändert verwendet.

{
  "Operations": [
    { "Name": "DefaultValueIfNullOrEmpty", "Parameters": { "DefaultValue": "unbekannt" } }
  ]
}

DefaultValueMap

(alle Konnektoren)

Übersetzt den ermittelten Wert anhand einer Zuordnungsliste. Der Schlüsselvergleich erfolgt ohne Beachtung der Groß-/Kleinschreibung.

{
  "Operations": [
    {
      "Name": "DefaultValueMap",
      "Parameters": {
        "Mapping": [
          { "Key": "DE", "Value": "Deutschland" },
          { "Key": "AT", "Value": "Österreich" }
        ]
      }
    }
  ]
}

Findet sich kein passender Schlüssel, bleibt der Wert unverändert — im Unterschied zu OptionMapping, das in diesem Fall einen Fehler wirft.

Lookup

(nur D365CE)

Befüllt ein Lookup-Feld in Dataverse, indem der verknüpfte Datensatz über einen Schlüssel gesucht wird.

{
  "Operations": [
    {
      "Name": "Lookup",
      "Parameters": {
        "TargetTable": "contact",
        "TargetKey": {
          "KeyType": "CustomKey",
          "KeyName": "wysa_number",
          "KeyValues": [
            { "keyName": "wysa_number", "attributeName": "contactNo", "rank": 1 }
          ]
        }
      }
    }
  ]
}

TargetTable ist zwingend — ohne diesen Parameter bricht die Auflösung ab.

ParameterBeschreibung
TargetTableEntität des zu suchenden Datensatzes (Pflicht)
TargetKeyEinzelner Schlüssel, Syntax wie beim TargetKey
TargetKeysArray mehrerer Schlüssel mit KeyRank (ab v2.1, siehe oben)
DoNotCreatetrue verhindert das automatische Anlegen (ab v2.1, siehe unten)
SetNullIfEqualsValueOfFieldSetzt das Lookup auf null, wenn der Wert dem angegebenen Feld der Nachricht entspricht — Schutz gegen Selbstreferenzen
DefaultValueFester Wert; überspringt die Auflösung vollständig

OptionMapping

(verfügbar: D365CE; bei D365BC und D365NAV für String-Felder)

Übersetzt Textwerte aus dem Quellsystem in numerische Optionset-Werte von Dataverse (und umgekehrt). Die Mapping-Liste enthält alle bekannten Schlüssel-Wert-Paare.

{
  "Operations": [
    {
      "Name": "OptionMapping",
      "Parameters": {
        "Mapping": [
          { "Key": "Blank",                       "Value": "" },
          { "Key": "Prospect",                    "Value": "383380000" },
          { "Key": "First_x002D_time_x0020_Donor","Value": "383380001" },
          { "Key": "Recurring_x0020_Donor",       "Value": "383380002" }
        ]
      }
    }
  ]
}

Für MultiSelect-Optionsets ist zusätzlich der Parameter OptionDelimiter anzugeben — er trennt die Einzelwerte im Quellstring. Ohne ihn schlägt die Aufteilung fehl.


Datentyp-Umwandlung

Welche Quelltypen ein Zielfeld akzeptiert, hängt vom Connector und vom Zielfeld-Typ ab. Die vollständigen Matrizen stehen auf den Konnektor-Seiten.

Zwei Punkte, die häufig zu Rückfragen führen:

String zu Dezimalzahl (ab v2.1) — Dezimalfelder akzeptieren jetzt auch Quellwerte vom Typ string. Diese werden immer im Format en-US interpretiert, also mit Punkt als Dezimaltrennzeichen. Ein leerer String wird zu null, ein nicht konvertierbarer Wert erzeugt einen Fehler.

Culture bei echten Zahlentypen — kommt der Wert dagegen bereits als decimal oder money, gilt die im Verbindungs-JSON eingestellte language (Vorgabe de-DE).


Spezialfälle

Feld ohne Quellwert (reiner Standardwert)

Soll ein Zielfeld immer mit einem festen Wert befüllt werden, ohne dass ein Quellfeld existiert:

SpalteWert
SourceField(leer)
TargetFieldwysa_datasource
TargetOperationDefaultValue mit "DefaultValue": "DataBridge"

Wert aus der Antwortnachricht lesen (ResponseJob)

SpalteWert
SourceField_id
TargetFieldwysa_bcid
SourceOperationReadFromMessage

Siehe auch Virtuelle Felder und Jobs → ResponseJob.

Mehrere Operationen in einer Zeile

Ob mehrere Einträge im Operations-Array wirken, hängt davon ab, um welche Art von Operation es sich handelt:

Verhalten bei mehreren Einträgen
SourceOperationNur der erste Eintrag wird ausgeführt, alle weiteren verworfen
TargetOperationMehrere Einträge sind zulässig; sie werden über ihren Namen aufgelöst, nicht über die Reihenfolge. Es gilt die Rangfolge DefaultValue → DefaultValueIfNullOrEmpty → DefaultValueMap.

Eine Verkettung im Sinne von „erst A, dann B auf das Ergebnis von A" gibt es bei SourceOperations damit nicht.