Skip to content

Item Operations

Mark Lauter edited this page May 16, 2026 · 5 revisions

Item Operations

Overview

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.

PutItemAsync

Writes an item to a table. If an item with the same key already exists, it is replaced.

Signatures

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)

Parameters

  • 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 (#name placeholders)
  • ExpressionAttributeValues — value substitutions (:value placeholders)
  • ReturnValuesNONE (default) or ALL_OLD (returns the previous item, if one existed; response.Attributes is null when no prior item was found)

Example

// 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)

Exceptions

  • ResourceNotFoundException — table doesn't exist
  • ConditionalCheckFailedException — condition expression evaluated to false

GetItemAsync

Retrieves a single item by its primary key.

Signatures

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)

Parameters

  • 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)

Example

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);

Parity notes

  • ConsistentRead is accepted but all reads are strongly consistent by default (SQLite provides this naturally)
  • TTL-expired items are filtered out at read time

DeleteItemAsync

Deletes a single item by its primary key.

Signatures

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)

Parameters

  • 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
  • ReturnValuesNONE (default) or ALL_OLD (response.Attributes is null when no prior item existed)

Example

// 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
});

Exceptions

  • ResourceNotFoundException — table doesn't exist
  • ConditionalCheckFailedException — condition expression evaluated to false

UpdateItemAsync

Updates attributes of an existing item, or creates a new item if it doesn't exist (upsert behavior).

Signatures

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)

Parameters

  • 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
  • ReturnValuesNONE, ALL_OLD, ALL_NEW, UPDATED_OLD, or UPDATED_NEW
  • AttributeUpdates — legacy API (converted to UpdateExpression internally)

UpdateExpression clauses

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.

SET value expressions

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 behavior

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 behavior

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.

Example

// 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

ReturnValues modes

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

Validation

  • Key attributes cannot be modified via UpdateExpression (throws AmazonDynamoDBException)
  • Arithmetic operands must both be numeric — throws ArgumentException on type mismatch
  • list_append operands must both be lists — throws ArgumentException on type mismatch

Exceptions

  • ResourceNotFoundException — table doesn't exist
  • ConditionalCheckFailedException — condition expression evaluated to false
  • AmazonDynamoDBException — attempting to update a key attribute

Expression attribute substitution

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" }
};

Supported condition expression functions

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)

Supported condition expression operators

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

Next steps

Clone this wiki locally