Batch Requests
The OData interface implements the batch functionality of OData using Ometa context records if enabled through the interface script. Each context record is regarded as one request within the batch.
The interface will always send its requests within one changeset, in one batch. It's the responsibility of the external OData service to reject the entire changeset and revert prior to the request if one of the items is invalid. The request bodies in Using Batch Requests show how outgoing requests are generated.
Context Records
A context record contains the input parameters for executing a method. Multiple context records can be passed along for a method execution, and the interface will then execute the logic as defined (in the interface script) on the external system for each context record. Each context record then has its own output. By using multiple context records instead of multiple method executions, there is a performance benefit because fewer connections or interface processes are needed.
The framework utilizes context records in the following scenario's:
- The actions of synchronizations.
- View functions with 'Run Sequentially' enabled.
- Runtime service endpoints that are called with batch requests. See the Working With OData article for more information.
- Custom code using
Method.AddContextRecordfollowed byMethod.Execute.
Keep in mind that the Ometa Business Connector does not utilize context records when using 'Test Method'.
Refer to the common template parameters.
Interface Script Parameters
| Interface Script Parameter | Description |
|---|---|
| SendContextRecordsAsBatch | Indicate whether context records should be sent as a batch request, or one by one. If you wish to use batch requests, this must be specified and set to True. |
| CreateParentRequest | Indicate whether a parent or header item should be created for the entire batch, within the same batch. Using this option, without configuring SendContextRecordAsBatch=True will show an error. |
| ParentBatchReferenceField | The field in which the reference to the parent should be stored in each request of the batch. This is only valid when CreateParentRequest=True. Refer to the 'Using Batch Requests With A Parent' section for more information.. |
| ParentEntitySet | The entity set on which the parent should be created. This is only valid when CreateParentRequest=True. Refer to the 'Using Batch Requests With A Parent' section for more information.. |
| ParentFieldLinks | This field indicates which fields from the first records, should be used to create the parent. Each field required for the parent must be specified. Example: ParentFieldLink=ODataFieldNameOfParent=OmetaInputField. |
Using the SendContextRecordsAsBatch still allows the use of the other query options. However, these are bound to the interface script and cannot vary between context records. The order of these options does not matter.
Refer to the other query options in Reading Data.
OData Reference Service Examples
For these examples, the OData reference service is used. This is a publicly available OData service that can process batch requests. The reference service from odata.org can be found here: https://services.odata.org/V4/OData/(S(readwrite))/OData.svc/. The examples below use the v4 service, but will also work on v3 and v2.
The examples will be using the Products entity set for its queries. Note that the reference service replaces readwrite with an unique identifier. Use this identifier in the interface scripts.
Warning
The OData reference service used in this example does not validate input, inserting or updating entries with the duplicate ID's can corrupt the service instance. You can retrieve a new instance by changing the service identifier $(casxsbbcq1gqj2papztyglbq) in these examples.
Using Batch Requests
Single Get
Entity Set=Products
Operation=SingleGet
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
Multi Get
Note that the filter can not be set per context record, therefore calling a multi get in batch doesn't have much purpose. Nevertheless, below is a sample configuration for completion's sake.
Entity Set=Products
Operation=MultiGet
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
Insert / Create
This sample creates multiple new products on the Products entity set. If you require that another entity must be created within the same batch as a header / parent, refer to the sections using refer to the section using CreateParentRequest.
Entity Set=Products
Operation=Insert
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
Update / Modify
This sample below updates the DiscontinuedDate on one product, and the Price on another. If you require that another entity must be created within the same batch as a header / parent, refer to the section using CreateParentRequest.
Older OData services may not return an output for batch updates, thus doing a new single get, or multi get may be required to see the results.
Entity Set=Products
Operation=Update
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
Remove / Delete
The sample below deletes multiple products. Delete operations do not return any results.
Entity Set=Products
Operation=Delete
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
Using Batch Requests With A Parent
Some OData services have a requirement that an entry must have a header (or parent) within the same batch. Common examples of this are order lines and order headers where a header may not be created without order lines, but an order line requires an order header.
Other examples include:
- A product and product specifications
- Invoice with at least one invoice line.
- A product and a supplier for our samples, even tough there is no validation defined in the service.
The parent in these examples is the entity that must be created first, and that can have multiple children:
- Product with multiple specifications.
- Invoice with multiple invoice lines.
- Supplier with multiple products.
To resolve this, the CreateParentRequest option can be used. This option indicates that for the entire batch, one parent entity must be created within that same batch. In order to facilitate this, the first context record must contain the data needed to create the parent. To define which fields from the first context record should be used to create the parent, the ParentFieldLink option must be specified for each field that the parent needs. The entity set on which the parent must be created can be specified using ParentEntitySet.
Lastly, the parent entity should be coupled to each child, this can be done using the ParentReferenceField. Note that this must be a field of the parent type, and not the identifier of the parent. If you do not specify this field, the parent will be created, but not used in the children (e.g. a separate supplier, and product for the reference service). If the reference field is a collection, it will be sent with only the created parent entity.
Insert With A Parent
This sample below inserts 2 new products, where each product has the new supplier as well.
Entity Set=Products
Operation=Insert
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
CreateParentRequest=True
ParentBatchReferenceField=Supplier
ParentEntitySet=Suppliers
ParentFieldLink=ID=SupplierId
ParentFieldLink=Name=SupplierName
ParentFieldLink=Concurrency=SupplierConcurrency
As a reminder on the field links: the first field is the field on the OData model, the second is the name of the Ometa input field.
Update With A Parent
This sample below updates 2 products with a newly created supplier, and price.
Entity Set=Products
Operation=Update
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
CreateParentRequest=True
ParentBatchReferenceField=Supplier
ParentEntitySet=Suppliers
ParentFieldLink=ID=SupplierId
ParentFieldLink=Name=SupplierName
ParentFieldLink=Concurrency=SupplierConcurrency
As a reminder on the field links: the first field is the field on the OData model, the second is the name of the Ometa input field.
Delete With A Parent
Though it does not make much sense in this context of products and suppliers. Some services can implement some sort of header transaction for delete actions. Since there is no such thing for the reference service used in these examples, we'll regard the supplier as our header regardless.
The difference in configuration here is that there is no ParentReferenceField configured. The interface will therefore create a parent without attaching it to the other requests. This concept can also be applied for single get and multi get, which will be used rarely in practice.
Entity Set=Products
Operation=Delete
Service Url=https://services.odata.org/V4/OData/(S(casxsbbcq1gqj2papztyglbq))/OData.svc/
SendContextRecordsAsBatch=True
CreateParentRequest=True
ParentBatchReferenceField=Supplier
ParentEntitySet=Suppliers
ParentFieldLink=ID=SupplierId
ParentFieldLink=Name=SupplierName
ParentFieldLink=Concurrency=SupplierConcurrency
Notice how no reference field is configured here, since there is no update or insert happening. The supplier will be created without any references to the deleted products or vice versa.
As a reminder on the field links: the first field is the field on the OData model, the second is the name of the Ometa input field.