Ausführen von Batchbetrieben mithilfe der Web-API

Sie können mehrere Vorgänge in einer einzelnen HTTP-Anforderung gruppieren mithilfe des Batchvorgangs. Diese Vorgänge werden nacheinander in der angegebenen Reihenfolge ausgeführt. Die Reihenfolge der Antworten entspricht der Reihenfolge der Anfragen im Batch-Vorgang.

Das Format zum Senden von $batch-Anforderungen ist in diesem Abschnitt der OData-Spezifikation definiert: 11.7 Stapelanfragen. Der Inhalt in diesem Artikel fasst die Spezifikationsanforderungen zusammen und bietet Dataverse-spezifische Informationen und Beispiele.

Verwenden der Batchanforderungen

Batchanforderungen bieten zwei Funktionen, die zusammen verwendet werden können:

  • Sie können Anforderungen für mehrere Vorgänge mit einer einzigen HTTP-Anforderung senden.

    • Batchanforderungen können bis zu 1.000 einzelne Anforderungen enthalten und können keine anderen Batchanforderungen enthalten.
    • Web-API-$batch-Anforderungen entsprechen der ExecuteMultiple-Nachricht, die im SDK für .NET verfügbar ist. Weitere Informationen: Mehrere Anforderungen mit dem SDK für .NET ausführen.
  • Sie können Anforderungen für Vorgänge mithilfe von Changesets gruppieren, sodass sie als einzelne Transaktion enthalten sind.

    • Möglicherweise möchten Sie einen Satz verwandter Datensätze so erstellen, aktualisieren oder löschen, dass sichergestellt ist, dass alle Vorgänge als Gruppe erfolgreich sind bzw. fehlschlagen.
    • Web-API-$batch-Anforderungen, die Änderungssätze verwenden, entsprechen der ExecuteTransaction-Nachricht, die im SDK für .NET verfügbar ist. Weitere Informationen: Führt Nachrichten in einer einzelnen Datenbanktransaktion aus

    Hinweis

    Beachten Sie, dass zugeordnete Entitäten leichter in einem einzelnen Vorgang erstellt werden können als in einer Batchanforderung. Weitere Informationen: Zusammenhängende Tabellenzeilen in einem Arbeitsgang erstellen

Batchanforderungen werden manchmal auch zum Senden von GET-Anforderungen verwendet, bei denen die Länge der URL die maximal zulässige URL-Länge überschreiten kann. Menschen verwenden Batch-Anforderungen, weil die URL für die Anforderung im Nachrichtentext enthalten ist, wobei eine URL mit bis zu 64 KB (65.536 Zeichen) zulässig ist. Das Senden komplexer Abfragen mit FetchXml kann zu langen URLs führen. Weitere Informationen: Verwenden Sie FetchXML innerhalb einer Batch-Anforderung.

Batchanforderungen sind im Vergleich zu anderen Vorgängen, die mit der Web-API ausgeführt werden können, schwieriger zu erstellen. Bei den rohen Anfordeungs- und Antworttexten handelt es sich im Wesentlichen um ein Textdokument, das bestimmten Anforderungen entsprechen muss. Um auf die Daten in einer Antwort zuzugreifen, müssen Sie den Text in der Antwort analysieren oder eine Hilfsbibliothek finden. Siehe .NET-Hilfsmethoden.

Batchanforderungen

Nutzen Sie eine POST-Anfrage, um eine Batch-Operation zu senden, die mehrere Anforderungen enthält.

Die POST-Batchanforderung müssen einen Inhaltstyp-Header mit einem Wert besitzen, der auf multipart/mixed festgelegt ist, mit einer boundary, die so eingerichtet ist, dass sie den Bezeichner des Batchs mithilfe dieses Musters einbezieht:

POST [Organization Uri]/api/data/v9.2/$batch HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: multipart/mixed; boundary="batch_<unique identifier>"

Der eindeutige Bezeichner muss kein GUID sein, aber einzigartig.

Jedem Element im Batch muss der Batchbezeichner vorausgehen mit einem Content-Type- und Inhaltstransferkodierung-Header wie im folgenden Beispiel:

--batch_<unique identifier>
Content-Type: application/http
Content-Transfer-Encoding: binary

Wichtig

Nur Nutzdatenelemente mit einem Batch-Bezeichner, der mit dem im Content-Type-Header gesendeten Batch-Bezeichner übereinstimmt, werden ausgeführt. Wenn kein Nutzdatenelement den Content-Type-Batch-Bezeichner verwendet, wird die Batch-Anforderung erfolgreich sein, ohne dass ein Nutzdatenelement ausgeführt wird.

Sie müssen alle anderen HTTP-Header für jedes Element im Stapel einbeziehen, um das Verhalten für diese Anforderung zu steuern. Header, die auf den $batch-Vorgang angewendet werden, werden nicht auf jedes Element angewendet. Wenn Sie beispielsweise eine GET-Anforderung einbeziehen und Anmerkungen anfordern möchten, müssen Sie den entsprechenden Prefer: odata.include-annotations="*"-Header zu jedem Element hinzufügen.

Das Ende der Batchanforderung muss einen Indikator für das Beenden wie im folgenden Beispiel enthalten:

--batch_<unique identifier>--

Hinweis

Das HTTP-Protokoll erfordert, dass alle Zeilenenden in $batch-Anforderungsnutzdaten CRLF sind. Andere Zeilenenden können Deserialisierungsfehler verursachen. Beispiel: System.ArgumentException: Stream was not readable.. Wenn Sie CRLF nicht verwenden können, können Sie am Ende der Anforderungsnutzdaten zwei Nicht-CRLF-Zeilenenden hinzufügen, um die meisten Deserialisierungsfehler zu beheben.

Das folgende Beispiel ist eine Batch-Anforderung ohne Änderungssätze. Dieses Beispiel:

  • Erstellt drei Aufgabendatensätze, die einem Konto mit der accountid gleich 00000000-0000-0000-0000-000000000001 zugeordnet sind.
  • Ruft die dem Konto zugeordneten Aufgabendatensätze ab.

Anforderung:

POST [Organization Uri]/api/data/v9.2/$batch HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: multipart/mixed; boundary="batch_80dd1615-2a10-428a-bb6f-0e559792721f"

--batch_80dd1615-2a10-428a-bb6f-0e559792721f
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 1 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_80dd1615-2a10-428a-bb6f-0e559792721f
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 2 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_80dd1615-2a10-428a-bb6f-0e559792721f
Content-Type: application/http
Content-Transfer-Encoding: binary

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 3 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_80dd1615-2a10-428a-bb6f-0e559792721f
Content-Type: application/http
Content-Transfer-Encoding: binary

GET /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)/Account_Tasks?$select=subject HTTP/1.1


--batch_80dd1615-2a10-428a-bb6f-0e559792721f--

Batchantworten

Bei Erfolg gibt die Batch-Antwort den HTTP-Status 200 OK zurück und jedes Element in der Antwort wird durch einen eindeutigen Guid-Bezeichnerwert getrennt, der nicht mit dem Batch-Anforderungswert übereinstimmt.

--batchresponse_<unique identifier>
Content-Type: application/http
Content-Transfer-Encoding: binary

Das Ende der Batch-Antwort enthält einen Indikator für das Beenden wie im folgenden Beispiel:

--batchresponse_<unique identifier>--

Das folgende Beispiel ist die Antwort auf das vorherige Beispiel einer Batch-Anforderung.

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_01346794-f2e2-4d45-8cc2-f97e09fe8916
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(d31ba648-c592-ed11-aad1-000d3a993550)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(d31ba648-c592-ed11-aad1-000d3a993550)


--batchresponse_01346794-f2e2-4d45-8cc2-f97e09fe8916
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(d41ba648-c592-ed11-aad1-000d3a993550)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(d41ba648-c592-ed11-aad1-000d3a993550)


--batchresponse_01346794-f2e2-4d45-8cc2-f97e09fe8916
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(d51ba648-c592-ed11-aad1-000d3a993550)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(d51ba648-c592-ed11-aad1-000d3a993550)


--batchresponse_01346794-f2e2-4d45-8cc2-f97e09fe8916
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#tasks(subject)",
  "value": [
    {
      "@odata.etag": "W/\"77180907\"",
      "subject": "Task 1 in batch",
      "activityid": "d31ba648-c592-ed11-aad1-000d3a993550"
    },
    {
      "@odata.etag": "W/\"77180910\"",
      "subject": "Task 2 in batch",
      "activityid": "d41ba648-c592-ed11-aad1-000d3a993550"
    },
    {
      "@odata.etag": "W/\"77180913\"",
      "subject": "Task 3 in batch",
      "activityid": "d51ba648-c592-ed11-aad1-000d3a993550"
    }
  ]
}
--batchresponse_01346794-f2e2-4d45-8cc2-f97e09fe8916--

Änderungssätze

Eine Batchanforderung kann neben individuellen Anforderungen auch Changesets enthalten. Wenn mehrere Vorgänge in einem Changeset enthalten sind, werden alle Vorgänge als unteilbar betrachtet. Ein atomarer Vorgang bedeutet, dass alle abgeschlossenen Vorgänge zurückgesetzt werden, wenn einer der Vorgänge fehlschlägt.

Hinweis

GET-Anfragen sind innerhalb von Changesets nicht zulässig. Ein GET-Vorgang sollte keine Daten ändern, daher gehört er nicht in ein Changeset.

Wie eine Batchanforderung müssen auch Changesets einen Content-Type-Header mit einem Wert besitzen, der auf multipart/mixed festgelegt ist, mit einer boundary, die so eingerichtet ist, dass sie den Bezeichner des Changesets mithilfe dieses Musters einbezieht:

Content-Type: multipart/mixed; boundary="changeset_<unique identifier>"

Der eindeutige Bezeichner muss kein GUID sein, aber einzigartig. Jedem Element im Änderungssatz muss der Änderungssatzbezeichner vorausgehen mit einem Content-Type- und Content-Transfer-Encoding-Header wie im folgenden Beispiel:

--changeset_<unique identifier>
Content-Type: application/http
Content-Transfer-Encoding: binary

Änderungssätze können eine auch einen Content-ID-Header mit einem eindeutigen Wert enthalten. Wenn diesem Wert $ vorangestellt wird, stellt er eine Variable dar, die eine URI für eine beliebige Entität in diesem Vorgang erhält. Wenn Sie z. B. den Wert auf 1 festlegen, können Sie über $1 später auf diese Entität zurückgreifen. Weitere Informationen: Verweis-URIs in einem Vorgang

Das Ende des Änderungssatzes muss einen Indikator für das Beenden wie das folgende Beispiel enthalten:

--changeset_<unique identifier>--

Das folgende Beispiel zeigt die Verwendung eines Changesets für Folgendes:

  • Gruppieren Sie die Erstellung von drei Aufgaben, die einem Konto mit dem accountid-Wert 00000000-0000-0000-0000-000000000001 zugeordnet sind.
  • Rufen Sie die erstellten Konten mithilfe einer GET-Anforderung außerhalb des Changesets ab.

Anforderung:

POST [Organization Uri]/api/data/v9.2/$batch HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: multipart/mixed; boundary="batch_22975cad-7f57-410d-be15-6363209367ea"

--batch_22975cad-7f57-410d-be15-6363209367ea
Content-Type: multipart/mixed; boundary="changeset_246e6bfe-89a4-4c77-b293-7a433f082e8a"

--changeset_246e6bfe-89a4-4c77-b293-7a433f082e8a
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 1 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--changeset_246e6bfe-89a4-4c77-b293-7a433f082e8a
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 2 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--changeset_246e6bfe-89a4-4c77-b293-7a433f082e8a
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 3 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--changeset_246e6bfe-89a4-4c77-b293-7a433f082e8a--

--batch_22975cad-7f57-410d-be15-6363209367ea
Content-Type: application/http
Content-Transfer-Encoding: binary

GET /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000001)/Account_Tasks?$select=subject HTTP/1.1


--batch_22975cad-7f57-410d-be15-6363209367ea--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_f27ef42d-51b0-4685-bac9-f468f844de2f
Content-Type: multipart/mixed; boundary=changesetresponse_64cc3fff-023a-45b0-b29d-df21583ffa15

--changesetresponse_64cc3fff-023a-45b0-b29d-df21583ffa15
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(e73ffc82-e292-ed11-aad1-000d3a9933c9)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(e73ffc82-e292-ed11-aad1-000d3a9933c9)


--changesetresponse_64cc3fff-023a-45b0-b29d-df21583ffa15
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(e83ffc82-e292-ed11-aad1-000d3a9933c9)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(e83ffc82-e292-ed11-aad1-000d3a9933c9)


--changesetresponse_64cc3fff-023a-45b0-b29d-df21583ffa15
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(e93ffc82-e292-ed11-aad1-000d3a9933c9)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(e93ffc82-e292-ed11-aad1-000d3a9933c9)


--changesetresponse_64cc3fff-023a-45b0-b29d-df21583ffa15--
--batchresponse_f27ef42d-51b0-4685-bac9-f468f844de2f
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#tasks(subject)",
  "value": [
    {
      "@odata.etag": "W/\"77181173\"",
      "subject": "Task 1 in batch",
      "activityid": "e73ffc82-e292-ed11-aad1-000d3a9933c9"
    },
    {
      "@odata.etag": "W/\"77181176\"",
      "subject": "Task 2 in batch",
      "activityid": "e83ffc82-e292-ed11-aad1-000d3a9933c9"
    },
    {
      "@odata.etag": "W/\"77181179\"",
      "subject": "Task 3 in batch",
      "activityid": "e93ffc82-e292-ed11-aad1-000d3a9933c9"
    }
  ]
}
--batchresponse_f27ef42d-51b0-4685-bac9-f468f844de2f--

Verweis-URIs in einem Vorgang

Sie können $parameter wie $1, $2 usw. innerhalb Changesets verwenden, um auf URIs zu verweisen, die für neue Entitäten zurückgegeben wurden, die zuvor im selben Changeset erstellt wurden. Weitere Informationen finden Sie in der OData v4.0-Spezifikation: 11.7.3.1 Verweisen auf Anforderungen in einem Changeset.

In diesem Abschnitt werden verschiedene Beispiele dazu aufgeführt, wie $parameter im Anforderungstext eines Batchvorgangs verwendet werden kann, um auf URIs zu verweisen.

Verweis-URIs im Anforderungstext

Das untengenannte Beispiel veranschaulicht, wie URI-Verweise in einem einzelnen Vorgang verwendet werden können.

Anforderung:

POST [Organization URI]/api/data/v9.2/$batch HTTP/1.1
Content-Type:  multipart/mixed;boundary=batch_AAA123
Accept:  application/json
OData-MaxVersion:  4.0
OData-Version:  4.0

--batch_AAA123
Content-Type: multipart/mixed; boundary=changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

POST [Organization URI]/api/data/v9.2/leads HTTP/1.1
Content-Type: application/json

{
    "firstname":"first name",
    "lastname":"last name"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
Content-Type: application/json

{"firstname":"first name"}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
Content-Type: application/json

{
    "name":"IcM Account",
    "originatingleadid@odata.bind":"$1",
    "primarycontactid@odata.bind":"$2"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab--
--batch_AAA123--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_3cace264-86ea-40fe-83d3-954b336c0f4a
Content-Type: multipart/mixed; boundary=changesetresponse_1a5db8a1-ec98-42c4-81f6-6bc6adcfa4bc

--changesetresponse_1a5db8a1-ec98-42c4-81f6-6bc6adcfa4bc
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/leads(425195a4-7a75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/leads(425195a4-7a75-e911-a97a-000d3a34a1bd)

--changesetresponse_1a5db8a1-ec98-42c4-81f6-6bc6adcfa4bc
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/contacts(495195a4-7a75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/contacts(495195a4-7a75-e911-a97a-000d3a34a1bd)

--changesetresponse_1a5db8a1-ec98-42c4-81f6-6bc6adcfa4bc
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/accounts(4f5195a4-7a75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/accounts(4f5195a4-7a75-e911-a97a-000d3a34a1bd)

--changesetresponse_1a5db8a1-ec98-42c4-81f6-6bc6adcfa4bc--
--batchresponse_3cace264-86ea-40fe-83d3-954b336c0f4a--

Verweis-URI in der Anforderungs-URL

Das folgende Beispiel zeigt, wie Sie mit $1 auf einen URI in der URL einer nachfolgenden Anforderung verweisen können.

Anforderung:

POST [Organization URI]/api/data/v9.2/$batch HTTP/1.1
Content-Type:  multipart/mixed;boundary=batch_AAA123
Accept:  application/json
OData-MaxVersion:  4.0
OData-Version:  4.0

--batch_AAA123
Content-Type: multipart/mixed; boundary=changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
Content-Type: application/json

{
  "firstname":"First Name",
  "lastname":"Last name"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Transfer-Encoding: binary
Content-Type: application/http
Content-ID: 2

PUT $1/lastname HTTP/1.1
Content-Type: application/json

{
  "value":"BBBBB"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab--
--batch_AAA123--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_2cb48f48-39a8-41ea-aa52-132fa8ab3c2d
Content-Type: multipart/mixed; boundary=changesetresponse_d7528170-3ef3-41bd-be8e-eac971a8d9d4

--changesetresponse_d7528170-3ef3-41bd-be8e-eac971a8d9d4
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

HTTP/1.1 204 No Content
OData-Version: 4.0
Location:[Organization URI]/api/data/v9.2/contacts(f8ea5d2c-8c75-e911-a97a-000d3a34a1bd)
OData-EntityId:[Organization URI]/api/data/v9.2/contacts(f8ea5d2c-8c75-e911-a97a-000d3a34a1bd)


--changesetresponse_d7528170-3ef3-41bd-be8e-eac971a8d9d4
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

HTTP/1.1 204 No Content
OData-Version: 4.0


--changesetresponse_d7528170-3ef3-41bd-be8e-eac971a8d9d4--
--batchresponse_2cb48f48-39a8-41ea-aa52-132fa8ab3c2d--

Verweis-URIs in der URL und im Anforderungstext mit @odata.id

Das nachfolgende Beispiel zeigt, wie Sie einen Kontaktentitätsdatensatz mit einem Firmenentitätsdatensatz verknüpfen. Auf den URI des Firmenentitätsdatensatzes wird als $1 verwiesen und auf den URI des Kontaktentitätsdatensatzes wird als $2 verwiesen.

Anforderung:

POST [Organization URI]/api/data/v9.2/$batch HTTP/1.1
Content-Type:multipart/mixed;boundary=batch_AAA123
Accept:application/json
OData-MaxVersion:4.0
OData-Version:4.0

--batch_AAA123
Content-Type: multipart/mixed; boundary=changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type:application/http
Content-Transfer-Encoding:binary
Content-ID:1

POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
Content-Type: application/json

{ "name":"Account Name"}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type:application/http
Content-Transfer-Encoding:binary
Content-ID:2

POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
Content-Type:application/json

{ "firstname":"Contact first name"}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type:application/http
Content-Transfer-Encoding:binary
Content-ID:3

PUT $1/primarycontactid/$ref HTTP/1.1
Content-Type:application/json

{"@odata.id":"$2"}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab--
--batch_AAA123--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_0740a25c-d8e1-41a5-9202-1b50a297864c
Content-Type: multipart/mixed; boundary=changesetresponse_19ca0da8-d8bb-4273-a3f7-fe0d0fadfe5f

--changesetresponse_19ca0da8-d8bb-4273-a3f7-fe0d0fadfe5f
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

HTTP/1.1 204 No Content
OData-Version: 4.0
Location:[Organization URI]/api/data/v9.2/accounts(3dcf8c02-8c75-e911-a97a-000d3a34a1bd)
OData-EntityId:[Organization URI]/api/data/v9.2/accounts(3dcf8c02-8c75-e911-a97a-000d3a34a1bd)

--changesetresponse_19ca0da8-d8bb-4273-a3f7-fe0d0fadfe5f
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

HTTP/1.1 204 No Content
OData-Version: 4.0
Location:[Organization URI]/api/data/v9.2/contacts(43cf8c02-8c75-e911-a97a-000d3a34a1bd)
OData-EntityId:[Organization URI]/api/data/v9.2/contacts(43cf8c02-8c75-e911-a97a-000d3a34a1bd)

--changesetresponse_19ca0da8-d8bb-4273-a3f7-fe0d0fadfe5f
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

HTTP/1.1 204 No Content
OData-Version: 4.0

--changesetresponse_19ca0da8-d8bb-4273-a3f7-fe0d0fadfe5f--
--batchresponse_0740a25c-d8e1-41a5-9202-1b50a297864c--

Verweis-URIs in der URL und Navigationseigenschaften

Das nachfolgende Beispiel zeigt, wie der Organisations-URI eines Kontaktdatensatzes verwendet wird und wie er unter Verwendung der einzelwertigen Navigationseigenschaft primarycontactid mit einem Firmendatensatz verknüpft wird. Auf den URI des Firmenentitätsdatensatzes wird als $1 verwiesen und auf den URI des Kontaktentitätsdatensatzes wird als $2 verwiesen in der Anforderung PATCH.

Anforderung:

POST [Organization URI]/api/data/v9.2/$batch HTTP/1.1
Content-Type:multipart/mixed;boundary=batch_AAA123
Accept:application/json
OData-MaxVersion:4.0
OData-Version:4.0

--batch_AAA123
Content-Type: multipart/mixed; boundary=changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
Content-Type: application/json

{ "name":"Account name"}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

POST [Organization URI]/api/data/v9.2/contacts HTTP/1.1
Content-Type: application/json

{
  "firstname":"Contact first name"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

PATCH $1 HTTP/1.1
Content-Type: application/json

{
  "primarycontactid@odata.bind":"$2"
}

--changeset_dd81ccab-11ce-4d57-b91d-12c4e25c3cab--
--batch_AAA123--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_9595d3ae-48f6-414f-a3aa-a3a33559859e
Content-Type: multipart/mixed; boundary=changesetresponse_0c1567a5-ad0d-48fa-b81d-e6db05cad01c

--changesetresponse_0c1567a5-ad0d-48fa-b81d-e6db05cad01c
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 1

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/accounts(6cd81853-7b75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/accounts(6cd81853-7b75-e911-a97a-000d3a34a1bd)

--changesetresponse_0c1567a5-ad0d-48fa-b81d-e6db05cad01c
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 2

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/contacts(6ed81853-7b75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/contacts(6ed81853-7b75-e911-a97a-000d3a34a1bd)

--changesetresponse_0c1567a5-ad0d-48fa-b81d-e6db05cad01c
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-ID: 3

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization URI]/api/data/v9.2/accounts(6cd81853-7b75-e911-a97a-000d3a34a1bd)
OData-EntityId: [Organization URI]/api/data/v9.2/accounts(6cd81853-7b75-e911-a97a-000d3a34a1bd)

--changesetresponse_0c1567a5-ad0d-48fa-b81d-e6db05cad01c--
--batchresponse_9595d3ae-48f6-414f-a3aa-a3a33559859e--

Hinweis

Wenn auf eine Content-ID verwiesen wird, bevor sie im Anforderungstext deklariert worden ist, wird der Fehler HTTP 400 ungültige Anforderung ausgegeben.

Das folgende Beispiel zeigt Anforderungstext an, der diesen Fehler verursachen kann.

Anforderungstext

--batch_AAA123
Content-Type: multipart/mixed; boundary=changeset_BBB456

--changeset_BBB456
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-ID: 2

POST [Organization URI]/api/data/v9.2/phonecalls HTTP/1.1
Content-Type: application/json;type=entry

{
    "phonenumber":"911",
    "regardingobjectid_account_phonecall@odata.bind" : "$1"
}

--changeset_BBB456
Content-Type: application/http
Content-Transfer-Encoding:binary
Content-ID: 1

POST [Organization URI]/api/data/v9.2/accounts HTTP/1.1
Content-Type: application/json;type=entry

{
    "name":"QQQQ",
    "revenue": 1.50
}

--changeset_BBB456--
--batch_AAA123--

Antwort:

HTTP 400 Bad Request
Content-ID Reference: '$1' does not exist in the batch context.

Behandeln von Fehlern

Wenn bei einer Anforderung innerhalb eines Batchs ein Fehler auftritt, wird der Fehler für diese Anforderung für die Batch-Anforderung zurückgegeben und weitere Anforderungen werden nicht verarbeitet.

Sie können den Prefer: odata.continue-on-error-Anforderungs-Header verwenden, um anzugeben, dass weitere Anforderungen verarbeitet werden, wenn Fehler auftreten. Die Batch-Anforderung gibt 200 OK zurück und einzelne Antwortfehler werden im Batch-Antworttext zurückgegeben.

Mehr Informationen: OData-Spezifikation: 8.2.8.3 Präferenz odata.continue-on-error

Beispiel

Im folgenden Beispiel wird versucht, drei Aufgabendatensätze zu erstellen, die einem Konto mit der accountid gleich 00000000-0000-0000-0000-000000000001 zugeordnet sind, aber die Länge der Eigenschaft subject für die erste Aufgabe ist zu lang.

Anforderung:

POST [Organization Uri]/api/data/v9.2/$batch HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: multipart/mixed; boundary="batch_431faf5a-f979-4ee6-a374-d242f8962d41"
Content-Length: 1335

--batch_431faf5a-f979-4ee6-a374-d242f8962d41
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 436

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Subject is too long xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_431faf5a-f979-4ee6-a374-d242f8962d41
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 250

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 2 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_431faf5a-f979-4ee6-a374-d242f8962d41
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 250

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 3 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_431faf5a-f979-4ee6-a374-d242f8962d41--

Ohne Festlegen des Prefer: odata.continue-on-error-Anforderungsheaders schlägt der Batch bei der ersten Anforderung im Batch fehl. Der Batchfehler stellt den Fehler der ersten fehlgeschlagenen Anforderung dar.

Antwort:

HTTP/1.1 400 BadRequest
OData-Version: 4.0

--batchresponse_156da4b8-cd2c-4862-a911-4aaab97c001a
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 400 Bad Request
REQ_ID: 5ecd1cb3-1730-4ffc-909c-d44c22270026
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0

{"error":{"code":"0x80044331","message":"A validation error occurred.  The length of the 'subject' attribute of the 'task' entity exceeded the maximum allowed length of '200'."}}
--batchresponse_156da4b8-cd2c-4862-a911-4aaab97c001a--

Wenn der Prefer: odata.continue-on-error-Anforderungsheader auf die Batchanforderung angewendet wird, ist die Batchanforderung mit dem Status 200 OK erfolgreich und der Fehler der ersten Anforderung wird als Teil des Haupttexts zurückgegeben.

Anforderung:

POST [Organization Uri]/api/data/v9.2/$batch HTTP/1.1
Prefer: odata.continue-on-error
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: multipart/mixed; boundary="batch_662d4610-7f12-4895-ac4a-3fdf77cc10a1"
Content-Length: 1338

--batch_662d4610-7f12-4895-ac4a-3fdf77cc10a1
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 439

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Subject is too long xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_662d4610-7f12-4895-ac4a-3fdf77cc10a1
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 250

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 2 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_662d4610-7f12-4895-ac4a-3fdf77cc10a1
Content-Type: application/http
Content-Transfer-Encoding: binary
Content-Length: 250

POST /api/data/v9.2/tasks HTTP/1.1
Content-Type: application/json; type=entry

{
  "subject": "Task 3 in batch",
  "regardingobjectid_account_task@odata.bind": "accounts(00000000-0000-0000-0000-000000000001)"
}
--batch_662d4610-7f12-4895-ac4a-3fdf77cc10a1--

Antwort:

HTTP/1.1 200 OK
OData-Version: 4.0

--batchresponse_f44bd09d-573f-4a30-bca0-2e500ee7e139
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 400 Bad Request
REQ_ID: de4c5227-4a28-4ebd-8ced-3392ece1697b
Content-Type: application/json; odata.metadata=minimal
OData-Version: 4.0

{"error":{"code":"0x80044331","message":"A validation error occurred.  The length of the 'subject' attribute of the 'task' entity exceeded the maximum allowed length of '200'."}}
--batchresponse_f44bd09d-573f-4a30-bca0-2e500ee7e139
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(aed2ae8b-3c94-ed11-aad1-000d3a9933c9)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(aed2ae8b-3c94-ed11-aad1-000d3a9933c9)


--batchresponse_f44bd09d-573f-4a30-bca0-2e500ee7e139
Content-Type: application/http
Content-Transfer-Encoding: binary

HTTP/1.1 204 No Content
OData-Version: 4.0
Location: [Organization Uri]/api/data/v9.2/tasks(b181a991-3c94-ed11-aad1-000d3a9933c9)
OData-EntityId: [Organization Uri]/api/data/v9.2/tasks(b181a991-3c94-ed11-aad1-000d3a9933c9)


--batchresponse_f44bd09d-573f-4a30-bca0-2e500ee7e139--

.NET-Hilfsmethoden

Die WebAPIService-Klassenbibliothek (C#) ist ein Beispielprojekt für eine Hilfsklassenbibliothek, das für in .NET geschriebene Web-API-Beispiele verwendet wird. Es zeigt eine Möglichkeit, wie gemeinsame Muster, die mit der Web-API verwendet werden, wiederverwendet werden können.

Hinweis

Diese Beispielbibliothek ist ein Helfer, der von allen Dataverse C#-Web-API-Beispielen verwendet wird, aber es ist kein SDK. Es wird nur getestet, um zu bestätigen, dass die Beispiele, die es verwenden, erfolgreich ausgeführt werden. Dieser Beispielcode wird „wie besehen“ ohne Gewährleistung für die Wiederverwendung bereitgestellt.

Diese Bibliothek enthält Klassen zum Erstellen von Batchanforderungen und zum Verarbeiten von Antworten. Beispielsweise wurden Variationen des folgenden Codes verwendet, um viele der HTTP-Anforderungs- und -Antwortbeispiele in diesem Artikel zu generieren.

using PowerApps.Samples;
using PowerApps.Samples.Batch;

static async Task Main()
{
    Config config = App.InitializeApp();

    var service = new Service(config);

    JObject account = new()
    {
        {"name","test account" }
    };

    EntityReference accountRef = await service.Create("accounts", account);

    List<HttpRequestMessage> createRequests = new() {
        new CreateRequest("tasks",new JObject(){
            {"subject","Task 2 in batch" },
            {"regardingobjectid_account_task@odata.bind", accountRef.Path }
        }),
        new CreateRequest("tasks",new JObject(){
            {"subject","Task 2 in batch" },
            {"regardingobjectid_account_task@odata.bind", accountRef.Path }
        }),
        new CreateRequest("tasks",new JObject(){
            {"subject","Task 3 in batch" },
            {"regardingobjectid_account_task@odata.bind", accountRef.Path }
        })
    };

    BatchRequest batchRequest = new(service.BaseAddress)
    {
        Requests = createRequests,
        ContinueOnError = true
    };

    var batchResponse = await service.SendAsync<BatchResponse>(batchRequest);

    batchResponse.HttpResponseMessages.ForEach(response => {

        string path = response.As<CreateResponse>().EntityReference.Path;
        Console.WriteLine($"Task created at: {path}");
        
    });
}

Ausgabe

Task created at: tasks(6743adfa-4a94-ed11-aad1-000d3a9933c9)
Task created at: tasks(6843adfa-4a94-ed11-aad1-000d3a9933c9)
Task created at: tasks(6943adfa-4a94-ed11-aad1-000d3a9933c9)

Innerhalb dieser Bibliothek gibt es einige Methoden, die Sie in Ihrem .NET-Code möglicherweise nützlich finden.

Weitere Informationen:

Beispiel einer .NET-HttpRequestMessage zu HttpMessageContent

In .NET müssen Sie Batchanforderungen als MultipartContent senden, eine Sammlung von HttpContent. HttpMessageContent erbt von HttpContent. Die WebAPIService-Klassenbibliothek (C#) BatchRequest-Klasse verwendet die folgende private statische ToMessageContent-Methode zum Konvertieren von HttpRequestMessage in HttpMessageContent, die zu MultipartContent hinzugefügt werden kann.

/// <summary>
/// Converts a HttpRequestMessage to HttpMessageContent
/// </summary>
/// <param name="request">The HttpRequestMessage to convert.</param>
/// <returns>HttpMessageContent with the correct headers.</returns>
private HttpMessageContent ToMessageContent(HttpRequestMessage request)
{

    //Relative URI is not allowed with MultipartContent
    request.RequestUri = new Uri(
        baseUri: ServiceBaseAddress,
        relativeUri: request.RequestUri.ToString());

    if (request.Content != null)
    {
        if (request.Content.Headers.Contains("Content-Type"))
        {
            request.Content.Headers.Remove("Content-Type");
        }
        request.Content.Headers.Add("Content-Type", "application/json;type=entry");
    }

    HttpMessageContent messageContent = new(request);

    if (messageContent.Headers.Contains("Content-Type"))
    {
        messageContent.Headers.Remove("Content-Type");
    }
    messageContent.Headers.Add("Content-Type", "application/http");
    messageContent.Headers.Add("Content-Transfer-Encoding", "binary");

    return messageContent;

}

Beispiel für eine .NET Parse-Batchantwort

Die WebAPIService-Klassenbibliothek (C#) BatchResponse-Klasse verwendet die folgende private statische ParseMultipartContent-Methode, um den Haupttext eines Batchs in eine List von HttpResponseMessage zu analysieren, die wie einzelne Antworten verarbeitet werden können.

/// <summary>
/// Processes the Multi-part content returned from the batch into a list of responses.
/// </summary>
/// <param name="content">The Content of the response.</param>
/// <returns></returns>
private static async Task<List<HttpResponseMessage>> ParseMultipartContent(HttpContent content)
{
   MultipartMemoryStreamProvider batchResponseContent = await content.ReadAsMultipartAsync();

   List<HttpResponseMessage> responses = new();

   if (batchResponseContent?.Contents != null)
   {
         batchResponseContent.Contents.ToList().ForEach(async httpContent =>
         {

            //This is true for changesets
            if (httpContent.IsMimeMultipartContent())
            {
               //Recursive call
               responses.AddRange(await ParseMultipartContent(httpContent));
            }

            //This is for individual responses outside of a change set.
            else
            {
               //Must change Content-Type for ReadAsHttpResponseMessageAsync method to work.
               httpContent.Headers.Remove("Content-Type");
               httpContent.Headers.Add("Content-Type", "application/http;msgtype=response");

               HttpResponseMessage httpResponseMessage = await httpContent.ReadAsHttpResponseMessageAsync();

               if (httpResponseMessage != null)
               {
                     responses.Add(httpResponseMessage);
               }
            }
         });
   }

   return responses;
}

Siehe auch

Vorgänge mithilfe der Web-API ausführen

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).