Skip to content
11 changes: 11 additions & 0 deletions generator/.DevConfigs/9490947f-209f-47e9-8c70-3698872df304.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"services": [
{
"serviceName": "DynamoDBv2",
"type": "minor",
"changeLogMessages": [
"Add Request Object Pattern and Expression-Based for DynamoDB Document Model."
]
}
]
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@ public abstract class DocumentOperationRequest
{
}

/// <summary>
/// Represents a request to get a single item from a DynamoDB table using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
/// Legacy parameters such as AttributesToGet are not supported. Use ProjectionExpression instead.
/// </summary>
public class GetItemDocumentOperationRequest : DocumentOperationRequest
{
/// <summary>
/// Gets or sets the key identifying the item in the table.
/// All key components (partition and sort key, if the table has one) must be provided.
/// </summary>
public IDictionary<string, DynamoDBEntry> Key { get; set; }

/// <summary>
/// Gets or sets the projection expression specifying which attributes should be retrieved.
/// If null, all attributes are returned.
/// </summary>
public Expression ProjectionExpression { get; set; }

/// <summary>
/// Gets or sets the consistent read flag.
/// Strongly consistent reads are only valid for tables and local secondary indexes.
/// </summary>
public bool ConsistentRead { get; set; }
}

/// <summary>
/// Represents a request to query items in a DynamoDB table using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
Expand All @@ -28,6 +54,7 @@ public QueryDocumentOperationRequest()

Limit = Int32.MaxValue;
Select = SelectValues.AllAttributes;
ReturnConsumedCapacity = ReturnConsumedCapacity.NONE;
}
/// <summary>
/// Gets or sets the key condition expression specifying which items should be returned.
Expand Down Expand Up @@ -82,5 +109,175 @@ public QueryDocumentOperationRequest()
/// This token should be retrieved from a Search object.
/// </summary>
public string PaginationToken { get; set; }

/// <summary>
/// Controls whether DynamoDB returns capacity consumption details for each Scan request.
/// Defaults to NONE. Set to TOTAL or INDEXES to capture consumed capacity metrics in Search.Metrics.
/// </summary>
public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; }
}

/// <summary>
/// Represents a request to scan items in a DynamoDB table or index using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
/// Legacy parameters such as ScanFilter, AttributesToGet are not supported.
/// Use FilterExpression and ProjectionExpression instead.
/// </summary>
public class ScanDocumentOperationRequest : DocumentOperationRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="ScanDocumentOperationRequest"/> class.
/// </summary>
public ScanDocumentOperationRequest()
{
Limit = Int32.MaxValue;
ConsistentRead = false;
Select = SelectValues.AllAttributes;
ReturnConsumedCapacity = ReturnConsumedCapacity.NONE;
}

/// <summary>
/// Gets or sets the filter expression specifying which items should be returned after scanning.
/// Applied after DynamoDB reads the items.
/// </summary>
public Expression FilterExpression { get; set; }

/// <summary>
/// Gets or sets the projection expression specifying which attributes should be retrieved.
/// </summary>
public Expression ProjectionExpression { get; set; }

/// <summary>
/// Enum specifying what data to return from the scan (e.g., attributes or count).
/// </summary>
public SelectValues Select { get; set; }

/// <summary>
/// Gets or sets the maximum number of items DynamoDB should process before returning a page of results.
/// Defaults to int.MaxValue (service default paging behavior).
/// </summary>
public int Limit { get; set; }

/// <summary>
/// Gets or sets the consistent read flag. Strongly consistent reads are only supported for tables and local secondary indexes.
/// </summary>
public bool ConsistentRead { get; set; }

/// <summary>
/// Gets or sets the index name to scan against.
/// </summary>
public string IndexName { get; set; }

/// <summary>
/// Whether to collect GetNextSet and GetRemaining results in Matches property.
/// Default is true. If set to false, Matches will always be empty.
/// </summary>
public bool CollectResults { get; set; }

/// <summary>
/// Pagination token corresponding to the item where the last Scan operation stopped.
/// Set this value to resume the scan from the next item. Retrieved from a Search object.
/// </summary>
public string PaginationToken { get; set; }

/// <summary>
/// The segment number to scan in a parallel scan. Must be between 0 and TotalSegments - 1 when specified.
/// If null, a non-parallel (single segment) scan is performed.
/// </summary>
public int Segment { get; set; }

/// <summary>
/// Total number of segments for a parallel scan. Defaults to 1 (no parallelism).
/// </summary>
public int TotalSegments { get; set; }

/// <summary>
/// Controls whether DynamoDB returns capacity consumption details for each Scan request.
/// Defaults to NONE. Set to TOTAL or INDEXES to capture consumed capacity metrics in Search.Metrics.
/// </summary>
public ReturnConsumedCapacity ReturnConsumedCapacity { get; set; }
}

/// <summary>
/// Represents a request to update an item in a DynamoDB table using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
/// Legacy parameters such as AttributeUpdates, Expected are not supported.
/// Use UpdateExpression and ConditionalExpression instead.
/// </summary>
public class UpdateItemDocumentOperationRequest : DocumentOperationRequest
{
/// <summary>
/// Gets or sets the key identifying the item in the table.
/// </summary>
public IDictionary<string, DynamoDBEntry> Key { get; set; }

/// <summary>
/// Gets or sets the attributes to be updated in the item.
/// </summary>
public Document Document { get; set; }

/// <summary>
/// Gets or sets the update expression specifying how attributes should be updated.
/// </summary>
public Expression UpdateExpression { get; set; }

/// <summary>
/// Gets or sets the conditional expression evaluated before the update is performed.
/// If false, a ConditionalCheckFailedException is thrown.
/// </summary>
public Expression ConditionalExpression { get; set; }

/// <summary>
/// Flag specifying what values should be returned.
/// </summary>
public ReturnValues ReturnValues { get; set; }
}

/// <summary>
/// Represents a request to delete an item from a DynamoDB table using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
/// Legacy parameters such as Expected are not supported.
/// Use ConditionalExpression instead.
/// </summary>
public class DeleteItemDocumentOperationRequest : DocumentOperationRequest
{
/// <summary>
/// Gets or sets the key identifying the item in the table.
/// </summary>
public IDictionary<string, DynamoDBEntry> Key { get; set; }

/// <summary>
/// Gets or sets the conditional expression specifying when the item should be deleted.
/// </summary>
public Expression ConditionalExpression { get; set; }

/// <summary>
/// Flag specifying what values should be returned.
/// </summary>
public ReturnValues ReturnValues { get; set; }
}

/// <summary>
/// Represents a request to put (create or replace) an item in a DynamoDB table using the Document Model.
/// This class introduces a modern expression-based API that replaces legacy parameter-based approaches.
/// Legacy parameters such as Expected are not supported.
/// Use ConditionalExpression instead.
/// </summary>
public class PutItemDocumentOperationRequest : DocumentOperationRequest
{
/// <summary>
/// Gets or sets the document to be put in the table.
/// </summary>
public Document Document { get; set; }

/// <summary>
/// Gets or sets the conditional expression specifying when the item should be put.
/// </summary>
public Expression ConditionalExpression { get; set; }

/// <summary>
/// Flag specifying what values should be returned.
/// </summary>
public ReturnValues ReturnValues { get; set; }
}
}
49 changes: 44 additions & 5 deletions sdk/src/Services/DynamoDBv2/Custom/DocumentModel/Expression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,13 @@
* permissions and limitations under the License.
*/

using Amazon.DynamoDBv2.Model;
using Amazon.Runtime.Internal;
using Amazon.Util;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;

using Amazon.DynamoDBv2.Model;
using Amazon.Util;

namespace Amazon.DynamoDBv2.DocumentModel
{
/// <summary>
Expand Down Expand Up @@ -157,6 +156,47 @@ internal void ApplyExpression(UpdateItemRequest request, Table table)
}
}

internal void ApplyConditionalExpression(UpdateItemRequest request, Table table)
{
request.ConditionExpression = this.ExpressionStatement;
MergeAttributes(request, table);
}

internal void ApplyUpdateExpression(UpdateItemRequest request, Table table)
{
request.UpdateExpression = this.ExpressionStatement;
MergeAttributes(request, table);
}

private void MergeAttributes(UpdateItemRequest request, Table table)
{
var convertToAttributeValues = ConvertToAttributeValues(this.ExpressionAttributeValues, table);
request.ExpressionAttributeValues ??= new Dictionary<string, AttributeValue>(StringComparer.Ordinal);
foreach (var kvp in convertToAttributeValues)
{
request.ExpressionAttributeValues[kvp.Key] = kvp.Value;
}


if (this.ExpressionAttributeNames?.Count > 0)
{
request.ExpressionAttributeNames ??= new Dictionary<string, string>(StringComparer.Ordinal);
foreach (var kvp in this.ExpressionAttributeNames)
{
if (!request.ExpressionAttributeNames.ContainsKey(kvp.Key))
{
request.ExpressionAttributeNames[kvp.Key] = kvp.Value;
}
}
}
}

internal void ApplyExpression(GetItemRequest request, Table table)
{
request.ProjectionExpression = ExpressionStatement;
request.ExpressionAttributeNames = new Dictionary<string, string>(this.ExpressionAttributeNames);
}

internal void ApplyExpression(Get request, Table table)
{
request.ProjectionExpression = ExpressionStatement;
Expand Down Expand Up @@ -207,7 +247,6 @@ internal void ApplyExpression(ConditionCheck request, Table table)
}
}


internal static void ApplyExpression(QueryRequest request, Table table,
Expression keyExpression, Expression filterExpression)
{
Expand Down
Loading