-
Notifications
You must be signed in to change notification settings - Fork 0
Batch Operations
Mark Lauter edited this page Jun 2, 2026
·
7 revisions
Batch operations read or write multiple items in a single call, potentially across multiple tables. BatchWriteItemAsync runs in a single SQLite transaction (all-or-nothing). BatchGetItemAsync reads each key sequentially on a shared connection — items reflect the state at read time, not a single transactional snapshot. See Batch Operations in the AWS docs.
Retrieves up to 100 items from one or more tables in a single call.
Task<BatchGetItemResponse> BatchGetItemAsync(BatchGetItemRequest request, CancellationToken ct = default)
Task<BatchGetItemResponse> BatchGetItemAsync(Dictionary<string, KeysAndAttributes> requestItems, CancellationToken ct = default)
Task<BatchGetItemResponse> BatchGetItemAsync(Dictionary<string, KeysAndAttributes> requestItems, ReturnConsumedCapacity returnConsumedCapacity, CancellationToken ct = default)-
RequestItems (required) — dictionary of table name to keys and optional projection
- Keys — list of primary keys to retrieve
- ProjectionExpression — attributes to return (per table)
- ExpressionAttributeNames — name substitutions (per table)
- Maximum 100 items total across all tables
- At least 1 table must be specified
var response = await client.BatchGetItemAsync(new BatchGetItemRequest
{
RequestItems = new Dictionary<string, KeysAndAttributes>
{
["Users"] = new KeysAndAttributes
{
Keys =
[
new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-1" }
},
new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-2" }
}
],
ProjectionExpression = "UserId, #n",
ExpressionAttributeNames = new Dictionary<string, string>
{
["#n"] = "Name"
}
},
["Orders"] = new KeysAndAttributes
{
Keys =
[
new Dictionary<string, AttributeValue>
{
["CustomerId"] = new() { S = "user-1" },
["OrderId"] = new() { S = "order-1" }
}
]
}
}
});
// Results organized by table name
var users = response.Responses["Users"];
var orders = response.Responses["Orders"];| Field | Description |
|---|---|
Responses |
Dictionary of table name to list of items |
UnprocessedKeys |
Always empty (DynamoDbLite processes all keys) |
-
UnprocessedKeysis always an empty dictionary — DynamoDbLite never partially fails - Throws
ResourceNotFoundExceptionif any requested table does not exist — the entire call is rejected before any reads occur - TTL-expired items are filtered out
-
ConsistentReadis accepted per table but has no effect — all reads use the same SQLite snapshot -
ProjectionExpressionis applied in memory after retrieval; all attributes are read from SQLite regardless of projection (no behavioral impact, only performance) -
ReturnConsumedCapacityis accepted but ignored — the response never includes capacity data
Writes (put or delete) up to 25 items across one or more tables in a single call. The 25-item cap is the default and is configurable — see Limits.
Task<BatchWriteItemResponse> BatchWriteItemAsync(BatchWriteItemRequest request, CancellationToken ct = default)
Task<BatchWriteItemResponse> BatchWriteItemAsync(Dictionary<string, List<WriteRequest>> requestItems, CancellationToken ct = default)-
RequestItems (required) — dictionary of table name to list of write requests
- Each
WriteRequestcontains either aPutRequest(withItem) or aDeleteRequest(withKey)
- Each
- Maximum 25 operations total across all tables by default. Raise or lower the cap with
MaxBatchWriteItems— handy for seeding more than 25 rows per call in tests - Duplicate keys (same table + PK + SK) are rejected
- At least 1 table must be specified
await client.BatchWriteItemAsync(new BatchWriteItemRequest
{
RequestItems = new Dictionary<string, List<WriteRequest>>
{
["Users"] =
[
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-1" },
["Name"] = new() { S = "Alice" }
}
}
},
new WriteRequest
{
PutRequest = new PutRequest
{
Item = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-2" },
["Name"] = new() { S = "Bob" }
}
}
},
new WriteRequest
{
DeleteRequest = new DeleteRequest
{
Key = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-3" }
}
}
}
]
}
});| Field | Description |
|---|---|
UnprocessedItems |
Always empty (DynamoDbLite processes all items) |
- All operations execute in a single SQLite transaction (all-or-nothing)
- Secondary indexes are maintained for all puts and deletes
- TTL epochs are computed for put operations if TTL is enabled
- Table statistics (item count, size) are updated per affected table
-
UnprocessedItemsis always empty — no partial failures - Throws
ResourceNotFoundExceptionif any requested table does not exist — the entire batch is rejected before any writes occur - No
ConditionExpressionsupport on individual write requests (matches DynamoDB; use Transactions for conditional writes) - Duplicate key detection happens before any writes — the entire batch is rejected if duplicates are found
-
ReturnConsumedCapacityis accepted but ignored — the response never includes capacity data - The 25-operation cap matches DynamoDB but is configurable via
MaxBatchWriteItems; raising it lets a single call exceed what real DynamoDB accepts
- Performance — batching is the top write-throughput lever; it amortizes per-operation overhead across the whole batch
- Transactions — all-or-nothing multi-item operations with conditions
Repo · NuGet · API Parity
Getting started
Reference
- Table Operations
- Item Operations
- Query and Scan
- Batch Operations
- Transactions
- Secondary Indexes
- TTL
- Tags and Admin
- DI and Configuration
- Concurrency
- Performance
- API Parity
- FAQ
Recipes
- DynamoDBContext for tests
- xUnit per-test isolation
- ASP.NET Core integration test fixture
- Migrating tests off DynamoDB Local
Internals