MongoDB

Update

6 samples, from the least code that works to complete workflows.

What an update does

Rule On MongoDB
What is written Only the attributes present ($set); a field left out keeps its value; null is stored as null
Which documents By the declared id (default), a declared key (ArxMatch.Key) or any fields (ArxMatch.Columns); match fields are never written
Nothing matched ARX2002 RecordNotFound
RequireSingleRow More than one match is ARX2003 and nothing changes
The id Can't change: MongoDB's _id is immutable (ARX8001)
Match values A document or array given as a match value is compared as data ($eq), never run as an operator
Concurrency Optional. Declare a version column (.Version(table, column) in the schema catalog) and every update checks it in the same statement (a read returns the version with each record, so read, change and update carries it): an entity that carries an old version is ARX2004 RecordChanged and nothing is written, and each update adds one to the version. .Version(table, column, required: true) refuses an update that doesn't carry it (ARX1001). Without a version column the last writer wins.
Rows by a condition Update finds rows by equal values: the id, a declared key, or columns you give values for (ArxMatch.Columns). To change every row that meets a condition (amount > 100), pass the values and an ArxFilterExpression to UpdateMultipleAsync(values, filter): one call, all or nothing, from 0.1.0-preview.5 (UpdateMultiple, Basics). Before that version: read the rows with RetrieveMultipleAsync and pass them to UpdateMultipleAsync.

The samples

Basics

The least code that works.

1Update one recordProgressive

The smallest update, in three scenarios: by the id Create returned, clearing a value, and a record that isn't there.

2Choose how the documents are foundProgressive

The three ways to find the documents to change, in four scenarios: by a declared key, by any fields (several documents), with RequireSingleRow, and many entities at once, all or nothing.

Real cases

What an application does: a small CRM and product catalogue.

1Catch an injection attemptProgressive

Two attacks on an update endpoint: an operator as a field name, and a match value built to match every document.

Advanced cases

Dependency injection, transactions, batch scopes and setting the service up.

1Update in a batch scopeAdvanced

Creates and updates in one batch scope, in two scenarios: committed when the body returns, and rolled back when the body throws.

2A security check around updates: batches, allowed fields, false positivesAdvanced

A security check around updates (SecurityGuard, in the project root), in four scenarios: an API batch of changes passes through; an attack hidden in one item refuses the whole batch and is logged; a list of allowed fields stops unknown names before ARX; and a false positive from your own configuration is reported as a bug, not an attack, so nobody is blocked.

3Set up the service from the database's schemaAdvanced

The service set up from the database instead of by hand, then updating through it, in two scenarios: preload the lead collection at startup, and updating with Strict on, where only the preloaded fields may be named.