-
Notifications
You must be signed in to change notification settings - Fork 0
Item Operations
DynamoDbLite supports the four core item operations: Put, Get, Delete, and Update. All operations support expressions (condition, projection, update) and expression attribute name/value substitution. See Working with Items in the AWS docs.
Writes an item to a table. If an item with the same key already exists, it is replaced.
Task<PutItemResponse> PutItemAsync(PutItemRequest request, CancellationToken ct = default)
Task<PutItemResponse> PutItemAsync(string tableName, Dictionary<string, AttributeValue> item, CancellationToken ct = default)
Task<PutItemResponse> PutItemAsync(string tableName, Dictionary<string, AttributeValue> item, ReturnValue returnValues, CancellationToken ct = default)- TableName (required) — target table
- Item (required) — the item to write (must include all key attributes)
- ConditionExpression — condition that must be true for the put to succeed
-
ExpressionAttributeNames — name substitutions (
#nameplaceholders) -
ExpressionAttributeValues — value substitutions (
:valueplaceholders) -
ReturnValues —
NONE(default) orALL_OLD(returns the previous item, if one existed;response.Attributesis null when no prior item was found)
// Simple put
await client.PutItemAsync("Users", new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" },
["Name"] = new() { S = "Alice" }
});
// Conditional put (only if item doesn't exist)
await client.PutItemAsync(new PutItemRequest
{
TableName = "Users",
Item = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" },
["Name"] = new() { S = "Alice" }
},
ConditionExpression = "attribute_not_exists(UserId)"
});
// Put with ALL_OLD return
var response = await client.PutItemAsync(new PutItemRequest
{
TableName = "Users",
Item = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" },
["Name"] = new() { S = "Bob" }
},
ReturnValues = ReturnValue.ALL_OLD
});
// response.Attributes contains the previous item (if any)-
ResourceNotFoundException— table doesn't exist -
ConditionalCheckFailedException— condition expression evaluated to false
Retrieves a single item by its primary key.
Task<GetItemResponse> GetItemAsync(GetItemRequest request, CancellationToken ct = default)
Task<GetItemResponse> GetItemAsync(string tableName, Dictionary<string, AttributeValue> key, CancellationToken ct = default)
Task<GetItemResponse> GetItemAsync(string tableName, Dictionary<string, AttributeValue> key, bool? consistentRead, CancellationToken ct = default)- TableName (required) — target table
- Key (required) — the primary key of the item to retrieve
- ProjectionExpression — comma-separated list of attributes to return
- ExpressionAttributeNames — name substitutions for reserved words
- ConsistentRead — accepted but has no effect (all reads are consistent)
var response = await client.GetItemAsync(new GetItemRequest
{
TableName = "Users",
Key = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" }
},
ProjectionExpression = "#n, Age",
ExpressionAttributeNames = new Dictionary<string, string>
{
["#n"] = "Name"
}
});
if (response.IsItemSet)
Console.WriteLine(response.Item["Name"].S);-
ConsistentReadis accepted but all reads are strongly consistent by default (SQLite provides this naturally) - TTL-expired items are filtered out at read time
Deletes a single item by its primary key.
Task<DeleteItemResponse> DeleteItemAsync(DeleteItemRequest request, CancellationToken ct = default)
Task<DeleteItemResponse> DeleteItemAsync(string tableName, Dictionary<string, AttributeValue> key, CancellationToken ct = default)
Task<DeleteItemResponse> DeleteItemAsync(string tableName, Dictionary<string, AttributeValue> key, ReturnValue returnValues, CancellationToken ct = default)- TableName (required) — target table
- Key (required) — the primary key of the item to delete
- ConditionExpression — condition that must be true for the delete to succeed
- ExpressionAttributeNames / ExpressionAttributeValues — expression substitutions
-
ReturnValues —
NONE(default) orALL_OLD(response.Attributesis null when no prior item existed)
// Conditional delete
var response = await client.DeleteItemAsync(new DeleteItemRequest
{
TableName = "Users",
Key = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" }
},
ConditionExpression = "#s = :status",
ExpressionAttributeNames = new Dictionary<string, string> { ["#s"] = "Status" },
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
[":status"] = new() { S = "inactive" }
},
ReturnValues = ReturnValue.ALL_OLD
});-
ResourceNotFoundException— table doesn't exist -
ConditionalCheckFailedException— condition expression evaluated to false
Updates attributes of an existing item, or creates a new item if it doesn't exist (upsert behavior).
Task<UpdateItemResponse> UpdateItemAsync(UpdateItemRequest request, CancellationToken ct = default)
// Legacy AttributeUpdates overloads (deprecated — prefer UpdateExpression on the request object)
Task<UpdateItemResponse> UpdateItemAsync(string tableName, Dictionary<string, AttributeValue> key, Dictionary<string, AttributeValueUpdate> attributeUpdates, CancellationToken ct = default)
Task<UpdateItemResponse> UpdateItemAsync(string tableName, Dictionary<string, AttributeValue> key, Dictionary<string, AttributeValueUpdate> attributeUpdates, ReturnValue returnValues, CancellationToken ct = default)- TableName (required) — target table
- Key (required) — the primary key of the item to update
- UpdateExpression — expression describing the update (preferred)
- ConditionExpression — condition that must be true for the update to succeed
- ExpressionAttributeNames / ExpressionAttributeValues — expression substitutions
-
ReturnValues —
NONE,ALL_OLD,ALL_NEW,UPDATED_OLD, orUPDATED_NEW - AttributeUpdates — legacy API (converted to UpdateExpression internally)
| Clause | Syntax | Description |
|---|---|---|
SET |
SET path = value |
Set attribute values (see SET value expressions below) |
REMOVE |
REMOVE #a, #b |
Remove attributes |
ADD |
ADD path :val |
Add to a number or insert elements into a set (numbers, string sets, number sets, binary sets) |
DELETE |
DELETE path :val |
Remove elements from a set (string sets, number sets, binary sets only) |
You can combine multiple clauses in a single expression: SET #a = :v REMOVE #b ADD #c :n DELETE #d :s.
The right-hand side of a SET action supports several forms:
| Form | Example | Description |
|---|---|---|
| Value reference | SET #a = :val |
Assign a literal value |
| Path reference | SET #a = #b |
Copy the value of another attribute |
Arithmetic (+) |
SET #a = #a + :inc |
Add two numeric values |
Arithmetic (-) |
SET #a = #a - :dec |
Subtract two numeric values |
if_not_exists |
SET #a = if_not_exists(#a, :default) |
Use the existing value if present, otherwise use the default |
list_append |
SET #a = list_append(#a, :newItems) |
Concatenate two lists |
Arithmetic — both operands must be numbers (N). Throws ArgumentException if either operand is a non-numeric type. Computation uses decimal precision internally, avoiding floating-point rounding for counter and financial use cases.
if_not_exists(path, default) — returns the current value at path if it exists, otherwise evaluates default. Commonly combined with arithmetic for atomic counters: SET ViewCount = if_not_exists(ViewCount, :zero) + :one.
list_append(list1, list2) — both operands must be lists (L). Throws ArgumentException if either operand is a non-list type. To prepend, swap the order: list_append(:newItems, #a).
ADD works with numbers and sets. If the attribute does not exist, ADD creates it with the provided value (regardless of supported type). When the attribute already exists, both operands must be the same type:
-
Number (
N) — adds the value to the existing number. -
String set (
SS) — performs a union, adding only elements not already in the set. -
Number set (
NS) — performs a union, adding only elements not already in the set. -
Binary set (
BS) — performs a union; duplicates are detected by content equality.
If the existing attribute and the provided value have mismatched types, ADD is silently ignored (no error, no change).
DELETE works with sets only. It removes elements from an existing set.
-
String set (
SS), number set (NS), binary set (BS) — removes matching elements from the set.
If the attribute does not exist, DELETE is a no-op. If the existing attribute and the provided value have mismatched types, DELETE is silently ignored.
// SET and REMOVE in one expression
var response = await client.UpdateItemAsync(new UpdateItemRequest
{
TableName = "Users",
Key = new Dictionary<string, AttributeValue>
{
["UserId"] = new() { S = "user-123" }
},
UpdateExpression = "SET #n = :name, Age = :age REMOVE OldField",
ExpressionAttributeNames = new Dictionary<string, string> { ["#n"] = "Name" },
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
[":name"] = new() { S = "Alice Updated" },
[":age"] = new() { N = "31" }
},
ReturnValues = ReturnValue.ALL_NEW
});
// response.Attributes contains the full updated item| Mode | Returns |
|---|---|
NONE |
Nothing |
ALL_OLD |
The entire item before the update |
ALL_NEW |
The entire item after the update |
UPDATED_OLD |
Only the modified attributes, with their old values |
UPDATED_NEW |
Only the modified attributes, with their new values |
- Key attributes cannot be modified via UpdateExpression (throws
AmazonDynamoDBException) - Arithmetic operands must both be numeric — throws
ArgumentExceptionon type mismatch -
list_appendoperands must both be lists — throwsArgumentExceptionon type mismatch
-
ResourceNotFoundException— table doesn't exist -
ConditionalCheckFailedException— condition expression evaluated to false -
AmazonDynamoDBException— attempting to update a key attribute
All operations that accept expressions support name and value substitution:
// Use #name for reserved words or special characters
ExpressionAttributeNames = new Dictionary<string, string>
{
["#s"] = "Status", // "Status" might be a reserved word
["#d"] = "Data.Nested" // dots in attribute names
};
// Use :value for literal values
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
[":active"] = new() { S = "active" },
[":threshold"] = new() { N = "100" }
};| Function | Example |
|---|---|
attribute_exists(path) |
attribute_exists(Email) |
attribute_not_exists(path) |
attribute_not_exists(DeletedAt) |
begins_with(path, substr) |
begins_with(Name, :prefix) |
contains(path, operand) |
contains(Tags, :tag) |
size(path) |
size(Items) > :limit |
attribute_type(path, type) |
attribute_type(Age, :type) |
| Operator | Example |
|---|---|
=, <>, <, <=, >, >=
|
Age >= :min |
BETWEEN ... AND ... |
Age BETWEEN :min AND :max |
IN |
Status IN (:a, :b, :c) |
AND, OR, NOT
|
#a = :x AND #b > :y |
- Query and Scan — querying by key conditions and scanning
- Batch Operations — reading and writing multiple items
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