Use a document model for DynamoDB using an AWS SDK
The following code example shows how to perform Create, Read, Update, and Delete (CRUD) and batch operations using a document model for DynamoDB and an AWS SDK.
For more information, see Document model.
- .NET
-
- AWS SDK for .NET
-
Note
There's more on GitHub. Find the complete example and learn how to set up and run in the AWS Code Examples Repository
. Perform CRUD operations using a document model.
/// <summary> /// Performs CRUD operations on an Amazon DynamoDB table. /// </summary> public class MidlevelItemCRUD { public static async Task Main() { var tableName = "ProductCatalog"; var sampleBookId = 555; var client = new AmazonDynamoDBClient(); var productCatalog = LoadTable(client, tableName); await CreateBookItem(productCatalog, sampleBookId); RetrieveBook(productCatalog, sampleBookId); // Couple of sample updates. UpdateMultipleAttributes(productCatalog, sampleBookId); UpdateBookPriceConditionally(productCatalog, sampleBookId); // Delete. await DeleteBook(productCatalog, sampleBookId); } /// <summary> /// Loads the contents of a DynamoDB table. /// </summary> /// <param name="client">An initialized DynamoDB client object.</param> /// <param name="tableName">The name of the table to load.</param> /// <returns>A DynamoDB table object.</returns> public static Table LoadTable(IAmazonDynamoDB client, string tableName) { Table productCatalog = Table.LoadTable(client, tableName); return productCatalog; } /// <summary> /// Creates an example book item and adds it to the DynamoDB table /// ProductCatalog. /// </summary> /// <param name="productCatalog">A DynamoDB table object.</param> /// <param name="sampleBookId">An integer value representing the book's ID.</param> public static async Task CreateBookItem(Table productCatalog, int sampleBookId) { Console.WriteLine("\n*** Executing CreateBookItem() ***"); var book = new Document { ["Id"] = sampleBookId, ["Title"] = "Book " + sampleBookId, ["Price"] = 19.99, ["ISBN"] = "111-1111111111", ["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" }, ["PageCount"] = 500, ["Dimensions"] = "8.5x11x.5", ["InPublication"] = new DynamoDBBool(true), ["InStock"] = new DynamoDBBool(false), ["QuantityOnHand"] = 0, }; // Adds the book to the ProductCatalog table. await productCatalog.PutItemAsync(book); } /// <summary> /// Retrieves an item, a book, from the DynamoDB ProductCatalog table. /// </summary> /// <param name="productCatalog">A DynamoDB table object.</param> /// <param name="sampleBookId">An integer value representing the book's ID.</param> public static async void RetrieveBook( Table productCatalog, int sampleBookId) { Console.WriteLine("\n*** Executing RetrieveBook() ***"); // Optional configuration. var config = new GetItemOperationConfig { AttributesToGet = new List<string> { "Id", "ISBN", "Title", "Authors", "Price" }, ConsistentRead = true, }; Document document = await productCatalog.GetItemAsync(sampleBookId, config); Console.WriteLine("RetrieveBook: Printing book retrieved..."); PrintDocument(document); } /// <summary> /// Updates multiple attributes for a book and writes the changes to the /// DynamoDB table ProductCatalog. /// </summary> /// <param name="productCatalog">A DynamoDB table object.</param> /// <param name="sampleBookId">An integer value representing the book's ID.</param> public static async void UpdateMultipleAttributes( Table productCatalog, int sampleBookId) { Console.WriteLine("\nUpdating multiple attributes...."); int partitionKey = sampleBookId; var book = new Document { ["Id"] = partitionKey, // List of attribute updates. // The following replaces the existing authors list. ["Authors"] = new List<string> { "Author x", "Author y" }, ["newAttribute"] = "New Value", ["ISBN"] = null, // Remove it. }; // Optional parameters. var config = new UpdateItemOperationConfig { // Gets updated item in response. ReturnValues = ReturnValues.AllNewAttributes, }; Document updatedBook = await productCatalog.UpdateItemAsync(book, config); Console.WriteLine("UpdateMultipleAttributes: Printing item after updates ..."); PrintDocument(updatedBook); } /// <summary> /// Updates a book item if it meets the specified criteria. /// </summary> /// <param name="productCatalog">A DynamoDB table object.</param> /// <param name="sampleBookId">An integer value representing the book's ID.</param> public static async void UpdateBookPriceConditionally( Table productCatalog, int sampleBookId) { Console.WriteLine("\n*** Executing UpdateBookPriceConditionally() ***"); int partitionKey = sampleBookId; var book = new Document { ["Id"] = partitionKey, ["Price"] = 29.99, }; // For conditional price update, creating a condition expression. var expr = new Expression { ExpressionStatement = "Price = :val", }; expr.ExpressionAttributeValues[":val"] = 19.00; // Optional parameters. var config = new UpdateItemOperationConfig { ConditionalExpression = expr, ReturnValues = ReturnValues.AllNewAttributes, }; Document updatedBook = await productCatalog.UpdateItemAsync(book, config); Console.WriteLine("UpdateBookPriceConditionally: Printing item whose price was conditionally updated"); PrintDocument(updatedBook); } /// <summary> /// Deletes the book with the supplied Id value from the DynamoDB table /// ProductCatalog. /// </summary> /// <param name="productCatalog">A DynamoDB table object.</param> /// <param name="sampleBookId">An integer value representing the book's ID.</param> public static async Task DeleteBook( Table productCatalog, int sampleBookId) { Console.WriteLine("\n*** Executing DeleteBook() ***"); // Optional configuration. var config = new DeleteItemOperationConfig { // Returns the deleted item. ReturnValues = ReturnValues.AllOldAttributes, }; Document document = await productCatalog.DeleteItemAsync(sampleBookId, config); Console.WriteLine("DeleteBook: Printing deleted just deleted..."); PrintDocument(document); } /// <summary> /// Prints the information for the supplied DynamoDB document. /// </summary> /// <param name="updatedDocument">A DynamoDB document object.</param> public static void PrintDocument(Document updatedDocument) { if (updatedDocument is null) { return; } foreach (var attribute in updatedDocument.GetAttributeNames()) { string stringValue = null; var value = updatedDocument[attribute]; if (value is null) { continue; } if (value is Primitive) { stringValue = value.AsPrimitive().Value.ToString(); } else if (value is PrimitiveList) { stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); } Console.WriteLine($"{attribute} - {stringValue}", attribute, stringValue); } } }
Perform batch write operations using a document model.
/// <summary> /// Shows how to use mid-level Amazon DynamoDB API calls to perform batch /// operations. /// </summary> public class MidLevelBatchWriteItem { public static async Task Main() { IAmazonDynamoDB client = new AmazonDynamoDBClient(); await SingleTableBatchWrite(client); await MultiTableBatchWrite(client); } /// <summary> /// Perform a batch operation on a single DynamoDB table. /// </summary> /// <param name="client">An initialized DynamoDB object.</param> public static async Task SingleTableBatchWrite(IAmazonDynamoDB client) { Table productCatalog = Table.LoadTable(client, "ProductCatalog"); var batchWrite = productCatalog.CreateBatchWrite(); var book1 = new Document { ["Id"] = 902, ["Title"] = "My book1 in batch write using .NET helper classes", ["ISBN"] = "902-11-11-1111", ["Price"] = 10, ["ProductCategory"] = "Book", ["Authors"] = new List<string> { "Author 1", "Author 2", "Author 3" }, ["Dimensions"] = "8.5x11x.5", ["InStock"] = new DynamoDBBool(true), ["QuantityOnHand"] = new DynamoDBNull(), // Quantity is unknown at this time. }; batchWrite.AddDocumentToPut(book1); // Specify delete item using overload that takes PK. batchWrite.AddKeyToDelete(12345); Console.WriteLine("Performing batch write in SingleTableBatchWrite()"); await batchWrite.ExecuteAsync(); } /// <summary> /// Perform a batch operation involving multiple DynamoDB tables. /// </summary> /// <param name="client">An initialized DynamoDB client object.</param> public static async Task MultiTableBatchWrite(IAmazonDynamoDB client) { // Specify item to add in the Forum table. Table forum = Table.LoadTable(client, "Forum"); var forumBatchWrite = forum.CreateBatchWrite(); var forum1 = new Document { ["Name"] = "Test BatchWrite Forum", ["Threads"] = 0, }; forumBatchWrite.AddDocumentToPut(forum1); // Specify item to add in the Thread table. Table thread = Table.LoadTable(client, "Thread"); var threadBatchWrite = thread.CreateBatchWrite(); var thread1 = new Document { ["ForumName"] = "S3 forum", ["Subject"] = "My sample question", ["Message"] = "Message text", ["KeywordTags"] = new List<string> { "S3", "Bucket" }, }; threadBatchWrite.AddDocumentToPut(thread1); // Specify item to delete from the Thread table. threadBatchWrite.AddKeyToDelete("someForumName", "someSubject"); // Create multi-table batch. var superBatch = new MultiTableDocumentBatchWrite(); superBatch.AddBatch(forumBatchWrite); superBatch.AddBatch(threadBatchWrite); Console.WriteLine("Performing batch write in MultiTableBatchWrite()"); // Execute the batch. await superBatch.ExecuteAsync(); } }
Scan a table using a document model.
/// <summary> /// Shows how to use mid-level Amazon DynamoDB API calls to scan a DynamoDB /// table for values. /// </summary> public class MidLevelScanOnly { public static async Task Main() { IAmazonDynamoDB client = new AmazonDynamoDBClient(); Table productCatalogTable = Table.LoadTable(client, "ProductCatalog"); await FindProductsWithNegativePrice(productCatalogTable); await FindProductsWithNegativePriceWithConfig(productCatalogTable); } /// <summary> /// Retrieves any products that have a negative price in a DynamoDB table. /// </summary> /// <param name="productCatalogTable">A DynamoDB table object.</param> public static async Task FindProductsWithNegativePrice( Table productCatalogTable) { // Assume there is a price error. So we scan to find items priced < 0. var scanFilter = new ScanFilter(); scanFilter.AddCondition("Price", ScanOperator.LessThan, 0); Search search = productCatalogTable.Scan(scanFilter); do { var documentList = await search.GetNextSetAsync(); Console.WriteLine("\nFindProductsWithNegativePrice: printing ............"); foreach (var document in documentList) { PrintDocument(document); } } while (!search.IsDone); } /// <summary> /// Finds any items in the ProductCatalog table using a DynamoDB /// configuration object. /// </summary> /// <param name="productCatalogTable">A DynamoDB table object.</param> public static async Task FindProductsWithNegativePriceWithConfig( Table productCatalogTable) { // Assume there is a price error. So we scan to find items priced < 0. var scanFilter = new ScanFilter(); scanFilter.AddCondition("Price", ScanOperator.LessThan, 0); var config = new ScanOperationConfig() { Filter = scanFilter, Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Title", "Id" }, }; Search search = productCatalogTable.Scan(config); do { var documentList = await search.GetNextSetAsync(); Console.WriteLine("\nFindProductsWithNegativePriceWithConfig: printing ............"); foreach (var document in documentList) { PrintDocument(document); } } while (!search.IsDone); } /// <summary> /// Displays the details of the passed DynamoDB document object on the /// console. /// </summary> /// <param name="document">A DynamoDB document object.</param> public static void PrintDocument(Document document) { Console.WriteLine(); foreach (var attribute in document.GetAttributeNames()) { string stringValue = null; var value = document[attribute]; if (value is Primitive) { stringValue = value.AsPrimitive().Value.ToString(); } else if (value is PrimitiveList) { stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); } Console.WriteLine($"{attribute} - {stringValue}"); } } }
Query and scan a table using a document model.
/// <summary> /// Shows how to perform mid-level query procedures on an Amazon DynamoDB /// table. /// </summary> public class MidLevelQueryAndScan { public static async Task Main() { IAmazonDynamoDB client = new AmazonDynamoDBClient(); // Query examples. Table replyTable = Table.LoadTable(client, "Reply"); string forumName = "Amazon DynamoDB"; string threadSubject = "DynamoDB Thread 2"; await FindRepliesInLast15Days(replyTable); await FindRepliesInLast15DaysWithConfig(replyTable, forumName, threadSubject); await FindRepliesPostedWithinTimePeriod(replyTable, forumName, threadSubject); // Get Example. Table productCatalogTable = Table.LoadTable(client, "ProductCatalog"); int productId = 101; await GetProduct(productCatalogTable, productId); } /// <summary> /// Retrieves information about a product from the DynamoDB table /// ProductCatalog based on the product ID and displays the information /// on the console. /// </summary> /// <param name="tableName">The name of the table from which to retrieve /// product information.</param> /// <param name="productId">The ID of the product to retrieve.</param> public static async Task GetProduct(Table tableName, int productId) { Console.WriteLine("*** Executing GetProduct() ***"); Document productDocument = await tableName.GetItemAsync(productId); if (productDocument != null) { PrintDocument(productDocument); } else { Console.WriteLine("Error: product " + productId + " does not exist"); } } /// <summary> /// Retrieves replies from the passed DynamoDB table object. /// </summary> /// <param name="table">The table we want to query.</param> public static async Task FindRepliesInLast15Days( Table table) { DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); var filter = new QueryFilter("Id", QueryOperator.Equal, "Id"); filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate); // Use Query overloads that take the minimum required query parameters. Search search = table.Query(filter); do { var documentSet = await search.GetNextSetAsync(); Console.WriteLine("\nFindRepliesInLast15Days: printing ............"); foreach (var document in documentSet) { PrintDocument(document); } } while (!search.IsDone); } /// <summary> /// Retrieve replies made during a specific time period. /// </summary> /// <param name="table">The table we want to query.</param> /// <param name="forumName">The name of the forum that we're interested in.</param> /// <param name="threadSubject">The subject of the thread, which we are /// searching for replies.</param> public static async Task FindRepliesPostedWithinTimePeriod( Table table, string forumName, string threadSubject) { DateTime startDate = DateTime.UtcNow.Subtract(new TimeSpan(21, 0, 0, 0)); DateTime endDate = DateTime.UtcNow.Subtract(new TimeSpan(1, 0, 0, 0)); var filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadSubject); filter.AddCondition("ReplyDateTime", QueryOperator.Between, startDate, endDate); var config = new QueryOperationConfig() { Limit = 2, // 2 items/page. Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Message", "ReplyDateTime", "PostedBy", }, ConsistentRead = true, Filter = filter, }; Search search = table.Query(config); do { var documentList = await search.GetNextSetAsync(); Console.WriteLine("\nFindRepliesPostedWithinTimePeriod: printing replies posted within dates: {0} and {1} ............", startDate, endDate); foreach (var document in documentList) { PrintDocument(document); } } while (!search.IsDone); } /// <summary> /// Perform a query for replies made in the last 15 days using a DynamoDB /// QueryOperationConfig object. /// </summary> /// <param name="table">The table we want to query.</param> /// <param name="forumName">The name of the forum that we're interested in.</param> /// <param name="threadName">The bane of the thread that we are searching /// for replies.</param> public static async Task FindRepliesInLast15DaysWithConfig( Table table, string forumName, string threadName) { DateTime twoWeeksAgoDate = DateTime.UtcNow - TimeSpan.FromDays(15); var filter = new QueryFilter("Id", QueryOperator.Equal, forumName + "#" + threadName); filter.AddCondition("ReplyDateTime", QueryOperator.GreaterThan, twoWeeksAgoDate); var config = new QueryOperationConfig() { Filter = filter, // Optional parameters. Select = SelectValues.SpecificAttributes, AttributesToGet = new List<string> { "Message", "ReplyDateTime", "PostedBy", }, ConsistentRead = true, }; Search search = table.Query(config); do { var documentSet = await search.GetNextSetAsync(); Console.WriteLine("\nFindRepliesInLast15DaysWithConfig: printing ............"); foreach (var document in documentSet) { PrintDocument(document); } } while (!search.IsDone); } /// <summary> /// Displays the contents of the passed DynamoDB document on the console. /// </summary> /// <param name="document">A DynamoDB document to display.</param> public static void PrintDocument(Document document) { Console.WriteLine(); foreach (var attribute in document.GetAttributeNames()) { string stringValue = null; var value = document[attribute]; if (value is Primitive) { stringValue = value.AsPrimitive().Value.ToString(); } else if (value is PrimitiveList) { stringValue = string.Join(",", (from primitive in value.AsPrimitiveList().Entries select primitive.Value).ToArray()); } Console.WriteLine($"{attribute} - {stringValue}"); } } }
For a complete list of AWS SDK developer guides and code examples, see Using DynamoDB with an AWS SDK. This topic also includes information about getting started and details about previous SDK versions.
Use Step Functions to invoke Lambda functions
Use a high-level object persistence model