Creating rows in batch
Many rows in one request, and what is atomic.
Every table that has {table}_create also has {table}_createMany:
order_create(order: OrderInput): Order
order_createMany(orders: [OrderInput]): [Order]
The argument is the table name pluralised, the result is a list in the same shape the single-row field returns. Both require the same role, so nothing new has to be granted.
One request, one dispatch
mutation {
order_createMany(orders: [
{ orderType: NORMAL_ORDER, customerNo: 10002,
orderLines: [{ productNo: "1001", quantity: 1 }, { productNo: "1002", quantity: 2 }] },
{ orderType: NORMAL_ORDER, customerNo: 10002,
orderLines: [{ productNo: "1001", quantity: 3 }] },
{ orderType: NORMAL_ORDER, customerNo: 10003,
orderLines: [{ productNo: "1002", quantity: 4 }] }
]) {
orderNo
customerNo
joindown_OrderLine { lineNo productNo quantity }
}
}
All three orders and their lines go to Visma in a single dispatch and come back read from the database in one query. Sending the same three orders as three separate mutations costs three round trips to the Visma web service.
Inline child rows work exactly as they do for _create: orders for order,
voucherLines for batch.
At most 500 rows per request. More than that is rejected before anything is written, as is an empty list - neither is silently treated as success.
What is atomic and what is not
Each row is atomic in itself. A rejected column value or a rejected child line takes
its whole order with it, lines included. This is Visma error escalation: the failing
assignment escalates to the row that owns it, so the row add fails too instead of leaving a
half-written order behind. order_create behaves the same way.
The batch as a whole is not atomic. Sibling rows have no common ancestor operation to escalate to, so orders that are fine are still created when another one fails:
{
"errors": [{ "message": "Customer 99999999 does not exist", "path": ["order_createMany"] }],
"data": { "order_createMany": [{ "orderNo": 569 }, { "orderNo": 570 }] }
}
Three orders were sent, the middle one named a customer that does not exist, and two were created. The error says which, and the returned list contains exactly what now exists - so a failed row is visible both ways, but it does not roll the others back. Re-sending a whole batch after a partial failure therefore duplicates the rows that did succeed. Send the failed rows, not the batch.
If you need all-or-nothing across several orders, create them one at a time and undo yourself on failure.
Reading rows back
The created rows are read back by their whole primary key. This used to match on a
single column, so creating a line on order 564 returned an unrelated line that merely
shared a line number - {"orderNo": 1, "lineNo": 1, "productNo": "312"} for a line that
was in fact written correctly to order 564. Tables whose key spans several columns
(OrderLine, Voucher, CrossReference, and others) were all affected, on _create and
_update alike.