Amazon DynamoDB
Create
10 samples, from the least code that works to complete workflows.
What a create does
| Rule | On DynamoDB |
|---|---|
| Where it goes | The model says: a table of the entity's own (.Table("product", partitionKey: "sku")), or a single table shared by several entities, whose keys are templates (PK = CUSTOMER#{customer_id}) |
| The keys | ARX writes the table's key attributes, the index keys and entity_type from the model; the entity gives the values the templates name |
| An index's attributes | A create may leave out an attribute an index key is made of (a GSI is sparse): the item is written without that index key and isn't in the index, so a query through the index doesn't find it. An update that writes some of an index key's attributes must give the rest (ARX1001), because ARX writes the whole index key again; give none to leave the index key as it is |
| The id | Supplied by the application: DynamoDB generates no ids, so a generated id is ARX8001 (give a Guid.CreateVersion7() or your own) |
| A duplicate | ARX3001 UniqueViolation: every create is a conditional put (attribute_not_exists) and never overwrites |
| Names | ASCII letters, digits and _; #, : (expression syntax) or SQL syntax is ARX1017; names reach DynamoDB only as placeholders |
| Key values | Escaped in templates (# is stored as %23, % as %25), so a value can't make another entity's key |
| Write sharding | .WriteSharding(entity, shards, by) adds #SHARD#n to the partition key, n from a stable hash of the by attribute |
| Size | An item over 400 KB is ARX4002 |
| Without a catalog | Nothing to resolve: the ArxDynamoModel declares every table's keys and ids, and DynamoDB declares no column types. The SQL providers' SchemaResolution doesn't apply |
Reference
Value types
| .NET value | Stored as |
|---|---|
string |
S (string); an empty key value is ARX1001 |
char |
S |
a plain enum |
refused (ARX1007): write (int)value or value.ToString(), or use a selection set |
int, long, short, byte and the unsigned types |
N (number) |
decimal |
N, exact up to 38 digits (more is ARX4001) |
double, float |
N; NaN and infinity are ARX4001 |
bool |
BOOL |
Guid |
S, D format (5f0c…-…) |
byte[], ArxBytea |
B (binary) |
ArxJsonB |
M (map) or L (list), its JSON parsed |
| an array or a list | L, a list of the values above |
ArxSelectionSetValue |
its code, checked against the catalog |
ArxEntityReference |
the referenced id, checked against the catalog (ARX1005) |
null |
NULL |
Dates and times
DynamoDB has no date type: ARX stores dates as sortable text, so a sort key or a condition on a date compares in time order.
| .NET value | Stored as |
|---|---|
DateTime (UTC) |
S, 2026-11-09T10:30:00.0000000Z (every tick kept) |
DateTime (Local) |
converted to UTC |
DateTime (Unspecified) |
taken as UTC |
DateTimeOffset |
its UTC instant (the offset isn't kept) |
DateOnly |
S, 2026-11-09 |
TimeOnly, TimeSpan |
S (09:30:00.0000000, 1.02:03:04) |
default(DateTime), default(DateTimeOffset), default(DateOnly) |
refused (ARX1013): they mean "not set" |
The samples
Basics
The least code that works.
1Create one record, in either designProgressiveThe smallest create, in the two designs DynamoDB tables are made in: an entity with a table of its own, then a customer and an order sharing one table through key templates.
The errors a create meets most, in three scenarios: a key that exists, a key attribute left out, and an id declared as generated, which DynamoDB can't do.
Real cases
What an application does: a small CRM and product catalogue.
1Store every kind of valueProgressiveWhat each .NET value becomes in DynamoDB, in two scenarios: numbers, text and flags; then dates, documents, lists and picklists.
A form whose fields become attributes, attacked three ways: an expression placeholder as a field name, SQL in a field name, and key separators in a value meant to land on another customer's key.
Advanced cases
Dependency injection, transactions, batch scopes and setting the service up.
1Create in an ARX transactionAdvancedWrites across tables in one ARX transaction, in two scenarios: committed together, and a commit that fails and writes nothing.
A security check around creates (SecurityGuard, in the project root), in three scenarios: a normal request, an attack that is logged, and repeated attacks that block the user.
The service set up from DynamoDB's own description of its tables, in two scenarios: preload the lead table's key at startup, then create with Strict on, where only the declared attributes may be written.
Set the service up for production, in three scenarios: depend on IArxDataService, check the server at startup, and trace and measure every call.
Use items whose attributes are named outside ARX's name rule, in three scenarios: declare an alias for each such attribute and create items through them, read and query by the aliases, and see what is still refused: the attribute's own name in a call, and an alias on an attribute the model names.
Log every ARX call through ILogger, in three scenarios: one line per call with its table and how long it took, a failed call with its ARX code (and the exception logged where it is caught), and only the calls worth keeping in production.