

The Amazon SDK for .NET V3 has entered maintenance mode.

We recommend that you migrate to [Amazon SDK for .NET V4](https://docs.amazonaws.cn/sdk-for-net/v4/developer-guide/welcome.html). For additional details and information on how to migrate, please refer to our [maintenance mode announcement](https://aws.amazon.com/blogs/developer/aws-sdk-for-net-v3-maintenance-mode-announcement/).

# Using Amazon DynamoDB NoSQL databases
DynamoDBUsing Amazon DynamoDB NoSQL databases

Updated information about the document and object persistence programming models. It is now possible to prevent certain latency or deadlock conditions due to cold-start and thread-pool behaviors.

**Note**  
The programming models in these topics are present in both .NET Framework and .NET (Core), but the calling conventions differ, whether synchronous or asynchronous.

The Amazon SDK for .NET supports Amazon DynamoDB, which is a fast NoSQL database service offered by Amazon. The SDK provides three programming models for communicating with DynamoDB: the *low-level* model, the *document* model, and the *object persistence* model.

The following information introduces these models and their APIs, provides examples for how and when to use them, and gives you links to additional DynamoDB programming resources in the Amazon SDK for .NET.

## Low-Level Model


The low-level programming model wraps direct calls to the DynamoDB service. You access this model through the [Amazon.DynamoDBv2](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/NDynamoDBv2.html) namespace.

Of the three models, the low-level model requires you to write the most code. For example, you must convert .NET data types to their equivalents in DynamoDB. However, this model gives you access to the most features.

The following examples show you how to use the low-level model to create a table, modify a table, and insert items into a table in DynamoDB.

### Creating a Table


In the following example, you create a table by using the `CreateTable` method of the `AmazonDynamoDBClient` class. The `CreateTable` method uses an instance of the `CreateTableRequest` class that contains characteristics such as required item attribute names, primary key definition, and throughput capacity. The `CreateTable` method returns an instance of the `CreateTableResponse` class.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

Console.WriteLine("Getting list of tables");
List<string> currentTables = client.ListTables().TableNames;
Console.WriteLine("Number of tables: " + currentTables.Count);
if (!currentTables.Contains("AnimalsInventory"))
{
    var request = new CreateTableRequest
    {
        TableName = "AnimalsInventory",
        AttributeDefinitions = new List<AttributeDefinition>
      {
        new AttributeDefinition
        {
          AttributeName = "Id",
          // "S" = string, "N" = number, and so on.
          AttributeType = "N"
        },
        new AttributeDefinition
        {
          AttributeName = "Type",
          AttributeType = "S"
        }
      },
        KeySchema = new List<KeySchemaElement>
      {
        new KeySchemaElement
        {
          AttributeName = "Id",
          // "HASH" = hash key, "RANGE" = range key.
          KeyType = "HASH"
        },
        new KeySchemaElement
        {
          AttributeName = "Type",
          KeyType = "RANGE"
        },
      },
        ProvisionedThroughput = new ProvisionedThroughput
        {
            ReadCapacityUnits = 10,
            WriteCapacityUnits = 5
        },
    };

    var response = client.CreateTable(request);

    Console.WriteLine("Table created with request ID: " +
      response.ResponseMetadata.RequestId);
}
```

### Verifying That a Table is Ready to Modify


Before you can change or modify a table, the table has to be ready for modification. The following example shows how to use the low-level model to verify that a table in DynamoDB is ready. In this example, the target table to check is referenced through the `DescribeTable` method of the `AmazonDynamoDBClient` class. Every five seconds, the code checks the value of the table’s `TableStatus` property. When the status is set to `ACTIVE`, the table is ready to be modified.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();      
var status = "";

do
{
  // Wait 5 seconds before checking (again).
  System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5));
        
  try
  {
    var response = client.DescribeTable(new DescribeTableRequest
    {
      TableName = "AnimalsInventory"
    });

    Console.WriteLine("Table = {0}, Status = {1}",
      response.Table.TableName,
      response.Table.TableStatus);

    status = response.Table.TableStatus;
  }
  catch (ResourceNotFoundException)
  {
    // DescribeTable is eventually consistent. So you might
    //   get resource not found. 
  }

} while (status != TableStatus.ACTIVE);
```

### Inserting an Item into a Table


In the following example, you use the low-level model to insert two items into a table in DynamoDB. Each item is inserted through the `PutItem` method of the `AmazonDynamoDBClient` class, using an instance of the `PutItemRequest` class. Each of the two instances of the `PutItemRequest` class takes the name of the table that the items will be inserted in, with a series of item attribute values.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();

var request1 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "1" }},
    { "Type", new AttributeValue { S = "Dog" }},
    { "Name", new AttributeValue { S = "Fido" }}
  }
};

var request2 = new PutItemRequest
{
  TableName = "AnimalsInventory",
  Item = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "2" }},
    { "Type", new AttributeValue { S = "Cat" }},
    { "Name", new AttributeValue { S = "Patches" }}
  }
};
        
client.PutItem(request1);
client.PutItem(request2);
```

## Document Model


The document programming model provides an easier way to work with data in DynamoDB. This model is specifically intended for accessing tables and items in tables. You access this model through the [Amazon.DynamoDBv2.DocumentModel](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/NDynamoDBv2DocumentModel.html) namespace.

Compared to the low-level programming model, the document model is easier to code against DynamoDB data. For example, you don’t have to convert as many .NET data types to their equivalents in DynamoDB. However, this model doesn’t provide access to as many features as the low-level programming model. For example, you can use this model to create, retrieve, update, and delete items in tables. However, to create the tables, you must use the low-level model. Compared to the object persistence model, this model requires you to write more code to store, load, and query .NET objects.

For more information about the DynamoDB document programming model, see [.NET: Document model](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html) in the [Amazon DynamoDB Developer Guide](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/).

The following sections provide information about how to create a representation of the desired DynamoDB table, and examples about how to use the document model to insert items into tables and get items from tables.

### Create a representation of the table


To perform data operations using the document model, you must first create an instance of the `Table` class that represents a specific table. There are two primary ways to do this.

**LoadTable method**

The first mechanism is to use one of the static `LoadTable` methods of the [https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTable.html](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTable.html) class, similar to the following example:

```
var client = new AmazonDynamoDBClient();
Table table = Table.LoadTable(client, "Reply");
```

**Note**  
While this mechanism works, under certain conditions, it can sometimes lead to additional latency or deadlocks due to cold-start and thread-pool behaviors. For more information about these behaviors, see the blog post [Improved DynamoDB Initialization Patterns for the Amazon SDK for .NET](https://amazonaws-china.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

**TableBuilder**

An alternative mechanism, the [https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTableBuilder.html) class, was introduced in [version 3.7.203 of the AWSSDK.DynamoDBv2 NuGet package](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203). This mechanism can address the behaviors mentioned above by removing certain implicit method calls; specifically, the `DescribeTable` method. This mechanism is used in a manner similar to the following example:

```
var client = new AmazonDynamoDBClient();
var table = new TableBuilder(client, "Reply")
    .AddHashKey("Id", DynamoDBEntryType.String)
    .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
    .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String, "Message", DynamoDBEntryType.String)
    .Build();
```

For more information about this alternative mechanism, see again the blog post [Improved DynamoDB Initialization Patterns for the Amazon SDK for .NET](https://amazonaws-china.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

### Inserting an item into a table


In the following example, a reply is inserted into the Reply table through the `PutItemAsync` method of the `Table` class. The `PutItemAsync` method takes an instance of the `Document` class; the `Document` class is simply a collection of initialized attributes.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, add a reply to the table.
var newReply = new Document();
newReply["Id"] = Guid.NewGuid().ToString();
newReply["ReplyDateTime"] = DateTime.UtcNow;
newReply["PostedBy"] = "Author1";
newReply["Message"] = "Thank you!";

await table.PutItemAsync(newReply);
```

### Getting an item from a table


In the following example, a reply is retrieved through the `GetItemAsync` method of the `Table` class. To determine the reply to get, the `GetItemAsync` method uses the hash-and-range primary key of the target reply.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DocumentModel;

// Create a representation of the "Reply" table
//  by using one of the mechanisms described previously.

// Then, get a reply from the table
//  where "guid" is the hash key and "datetime" is the range key.
var reply = await table.GetItemAsync(guid, datetime);
Console.WriteLine("Id = " + reply["Id"]);
Console.WriteLine("ReplyDateTime = " + reply["ReplyDateTime"]);
Console.WriteLine("PostedBy = " + reply["PostedBy"]);
Console.WriteLine("Message = " + reply["Message"]);
```

The preceding example implicitly converts the table values to strings for the `WriteLine` method. You can do explicit conversions by using the various "As[type]" methods of the `DynamoDBEntry` class. For example, you can explicitly convert the value for `Id` from a `Primitive` data type to a GUID through the `AsGuid()` method:

```
var guid = reply["Id"].AsGuid();
```

## Object Persistence Model


The object persistence programming model is specifically designed for storing, loading, and querying .NET objects in DynamoDB. You access this model through the [Amazon.DynamoDBv2.DataModel](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/NDynamoDBv2DataModel.html) namespace.

Of the three models, the object persistence model is the easiest to code against whenever you are storing, loading, or querying DynamoDB data. For example, you work with DynamoDB data types directly. However, this model provides access only to operations that store, load, and query .NET objects in DynamoDB. For example, you can use this model to create, retrieve, update, and delete items in tables. However, you must first create your tables using the low-level model, and then use this model to map your .NET classes to the tables.

For more information about the DynamoDB object persistence programming model, see [.NET: Object persistence model](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html) in the [Amazon DynamoDB Developer Guide](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/).

The following examples show you how to define a .NET class that represents a DynamoDB item, use an instance of the .NET class to insert an item into a DynamoDB table, and use an instance of the .NET class to get an item from the table.

### Defining a .NET class that represents an item in a table


In the following example of a class definition, the `DynamoDBTable` attribute specifies the table name, while the `DynamoDBHashKey` and `DynamoDBRangeKey` attributes model the table's hash-and-range primary key. The `DynamoDBGlobalSecondaryIndexHashKey` attribute is defined so that a query for replies by a specific author can be constructed.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

[DynamoDBTable("Reply")]
public class Reply
{
    [DynamoDBHashKey]
    public string Id { get; set; }

    [DynamoDBRangeKey(StoreAsEpoch = false)]
    public DateTime ReplyDateTime { get; set; }

    [DynamoDBGlobalSecondaryIndexHashKey("PostedBy-Message-Index",
        AttributeName ="PostedBy")]
    public string Author { get; set; }

    [DynamoDBGlobalSecondaryIndexRangeKey("PostedBy-Message-Index")]
    public string Message { get; set; }
}
```

### Creating a context for the object persistence model


To use the object persistence programming model for DynamoDB, you must create a context, which provides a connection to DynamoDB and enables you to access tables, perform various operations, and run queries.

**Basic context**

The following example shows how to create the most basic context.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client);
```

**Context with DisableFetchingTableMetadata property**

The following example shows how you might additionally set the `DisableFetchingTableMetadata` property of the `DynamoDBContextConfig` class to prevent implicit calls to the `DescribeTable` method.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

var client = new AmazonDynamoDBClient();
var context = new DynamoDBContext(client, new DynamoDBContextConfig
{
    DisableFetchingTableMetadata = true
});
```

If the `DisableFetchingTableMetadata` property is set to `false` (the default), as shown in the first example, you can omit attributes that describe the key and index structure of table items from the `Reply` class. These attributes will instead be inferred through an implicit call to the `DescribeTable` method. If `DisableFetchingTableMetadata` is set to `true`, as shown in the second example, methods of the object persistence model such as `SaveAsync` and `QueryAsync` rely entirely on the attributes defined in the `Reply` class. In this case, a call to the `DescribeTable` method doesn't occur.

**Note**  
Under certain conditions, calls to the `DescribeTable` method can sometimes lead to additional latency or deadlocks due to cold-start and thread-pool behaviors. For this reason, it is sometimes advantageous to avoid calls to that method.  
For more information about these behaviors, see the blog post [Improved DynamoDB Initialization Patterns for the Amazon SDK for .NET](https://amazonaws-china.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

### Using an instance of the .NET class to insert an item into a table


In this example, an item is inserted through the `SaveAsync` method of the `DynamoDBContext` class, which takes an initialized instance of the .NET class that represents the item.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Create an object that represents the new item.
var reply = new Reply()
{
    Id = Guid.NewGuid().ToString(),
    ReplyDateTime = DateTime.UtcNow,
    Author = "Author1",
    Message = "Thank you!"
};

// Insert the item into the table.
await context.SaveAsync<Reply>(reply, new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});
```

### Using an instance of a .NET class to get items from a table


In this example, a query is created to find all the records of "Author1" by using the `QueryAsync` method of the `DynamoDBContext` class. Then, items are retrieved through the query's `GetNextSetAsync` method.

```
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;

// Create an appropriate context for the object persistence programming model,
//  examples of which have been described earlier.

// Construct a query that finds all replies by a specific author.
var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig
{
    IndexName = "PostedBy-Message-index"
});

// Display the result.
var set = await query.GetNextSetAsync();
foreach (var item in set)
{
    Console.WriteLine("Id = " + item.Id);
    Console.WriteLine("ReplyDateTime = " + item.ReplyDateTime);
    Console.WriteLine("PostedBy = " + item.Author);
    Console.WriteLine("Message = " + item.Message);
}
```

### Additional information about the object persistence model


The examples and explanations shown above sometimes include a property of the `DynamoDBContext` class called `DisableFetchingTableMetadata`. This property, which was introduced in [version 3.7.203 of the AWSSDK.DynamoDBv2 NuGet package](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203), allows you to avoid certain conditions that might cause additional latency or deadlocks due to cold-start and thread-pool behaviors. For more information, see the blog post [Improved DynamoDB Initialization Patterns for the Amazon SDK for .NET](https://amazonaws-china.com/blogs/developer/improved-dynamodb-initialization-patterns-for-the-aws-sdk-for-net/).

The following is some additional information about this property.
+ This property can be set globally in your `app.config` or `web.config` file if you're using .NET Framework.
+ This property can be set globally by using the [https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/Amazon/TAWSConfigsDynamoDB.html](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/Amazon/TAWSConfigsDynamoDB.html) class, as shown in the following example.

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  ```
+ In some cases, you can't add DynamoDB attributes to a .NET class; for example, if the class is defined in a dependency. In such cases, it's possible to still take advantage of the `DisableFetchingTableMetadata` property. To do so, use the [https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTableBuilder.html](https://docs.amazonaws.cn/sdkfornet/v3/apidocs/items/DynamoDBv2/TTableBuilder.html) class in addition to the `DisableFetchingTableMetadata` property. The `TableBuilder` class was also introduced in [version 3.7.203 of the AWSSDK.DynamoDBv2 NuGet package](https://www.nuget.org/packages/AWSSDK.DynamoDBv2/3.7.203).

  ```
  // Set the DisableFetchingTableMetadata property globally
  // before constructing any context objects.
  AWSConfigsDynamoDB.Context.DisableFetchingTableMetadata = true;
  
  var client = new AmazonDynamoDBClient();
  var context = new DynamoDBContext(client);
  
  var table = new TableBuilder(client, "Reply")
      .AddHashKey("Id", DynamoDBEntryType.String)
      .AddRangeKey("ReplyDateTime", DynamoDBEntryType.String)
      .AddGlobalSecondaryIndex("PostedBy-Message-index", "Author", DynamoDBEntryType.String,
          "Message", DynamoDBEntryType.String)
      .Build();
  
  // This registers the "Reply" table we constructed via the builder.
  context.RegisterTableDefinition(table);
  
  // Now operations like this will work,
  // even if the Reply class was not annotated with this index.
  var query = context.QueryAsync<Reply>("Author1", new DynamoDBOperationConfig()
  {
      IndexName = "PostedBy-Message-index"
  });
  ```

## More information


 **Using the Amazon SDK for .NET to program DynamoDB, information and examples**
+  [DynamoDB APIs](http://blogs.aws.amazon.com/net/post/Tx17SQHVEMW8MXC/DynamoDB-APIs) 
+  [DynamoDB Series Kickoff](http://blogs.aws.amazon.com/net/post/Tx2XQOCY08QMTKO/DynamoDB-Series-Kickoff) 
+  [DynamoDB Series - Document Model](http://blogs.aws.amazon.com/net/post/Tx2R0WG46GQI1JI/DynamoDB-Series-Document-Model) 
+  [DynamoDB Series - Conversion Schemas](http://blogs.aws.amazon.com/net/post/Tx2TCOGWG7ARUH5/DynamoDB-Series-Conversion-Schemas) 
+  [DynamoDB Series - Object Persistence Model](http://blogs.aws.amazon.com/net/post/Tx20L86FLMBW51P/DynamoDB-Series-Object-Persistence-Model) 
+  [DynamoDB Series - Expressions](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [Using Expressions with Amazon DynamoDB and the Amazon SDK for .NET](dynamodb-expressions.md) 
+  [JSON support in Amazon DynamoDB](dynamodb-json.md) 

 **Low-Level model, information and examples** 
+  [Working with Tables Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetWorkingWithTables.html) 
+  [Working with Items Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [Querying Tables Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [Scanning Tables Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [Working with Local Secondary Indexes Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [Working with Global Secondary Indexes Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

 **Document model, information and examples** 
+  [DynamoDB Data Types](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DataModel.html#DataModel.DataTypes) 
+  [DynamoDBEntry](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/TDynamoDBv2DocumentModelDynamoDBEntry.html) 
+  [.NET: Document Model](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DotNetSDKMidLevel.html) 

 **Object persistence model, information and examples** 
+  [.NET: Object Persistence Model](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DotNetSDKHighLevel.html) 

 **Other useful information** 
+ See [Integrating Amazon with .NET Aspire](aspire-integrations.md) for information about developing with Amazon DynamoDB local through .NET Aspire.

**Topics**
+ [

## Low-Level Model
](#dynamodb-intro-apis-low-level)
+ [

## Document Model
](#dynamodb-intro-apis-document)
+ [

## Object Persistence Model
](#dynamodb-intro-apis-object-persistence)
+ [

## More information
](#dynamodb-intro-more-info)
+ [Using expressions](dynamodb-expressions.md)
+ [JSON support](dynamodb-json.md)

# Using Expressions with Amazon DynamoDB and the Amazon SDK for .NET
Using expressions

**Note**  
The information in this topic is specific to projects based on .NET Framework and the Amazon SDK for .NET version 3.3 and earlier.

The following code examples demonstrate how to use the Amazon SDK for .NET to program DynamoDB with expressions. *Expressions* denote the attributes you want to read from an item in a DynamoDB table. You also use expressions when writing an item, to indicate any conditions that must be met (also known as a *conditional update*) and how the attributes are to be updated. Some update examples are replacing the attribute with a new value, or adding new data to a list or a map. For more information, see [Reading and Writing Items Using Expressions](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/Expressions.html).

**Topics**
+ [

## Sample Data
](#dynamodb-expressions-sample-data)
+ [

## Get a Single Item by Using Expressions and the Item’s Primary Key
](#dynamodb-expressions-get-item)
+ [

## Get Multiple Items by Using Expressions and the Table’s Primary Key
](#dynamodb-expressions-query)
+ [

## Get Multiple Items by Using Expressions and Other Item Attributes
](#dynamodb-expressions-scan)
+ [

## Print an Item
](#dynamodb-expressions-print-item)
+ [

## Create or Replace an Item by Using Expressions
](#dynamodb-expressions-put-item)
+ [

## Update an Item by Using Expressions
](#dynamodb-expressions-update-item)
+ [

## Delete an Item by Using Expressions
](#dynamodb-expressions-delete-item)
+ [

## More Info
](#dynamodb-expressions-resources)

## Sample Data


The code examples in this topic rely on the following two example items in a DynamoDB table named `ProductCatalog`. These items describe information about product entries in a fictitious bicycle store catalog. These items are based on the example provided in [Case Study: A ProductCatalog Item](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/Expressions.CaseStudy.html). The data type descriptors such as `BOOL`, `L`, `M`, `N`, `NS`, `S`, and `SS` correspond to those in the [JSON Data Format](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DataFormat.html).

```
{
  "Id": {
    "N": "205"
  },
  "Title": {
    "S": "20-Bicycle 205"
  },
  "Description": {
    "S": "205 description"
  },
  "BicycleType": {
    "S": "Hybrid"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "500"
  },
  "Gender": {
    "S": "B"
  },
  "Color": {
    "SS": [
      "Red",
      "Black"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "1"
  },
  "RelatedItems": {
    "NS": [
      "341",
      "472",
      "649"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/205_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/205_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/205_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "Excellent! Can't recommend it highly enough! Buy it!",
          "Do yourself a favor and buy this."
        ]
      },
      "OneStar": {
        "SS": [
          "Terrible product! Do not buy this."
        ]
      }
    }
  }
},
{
  "Id": {
    "N": "301"
  },
  "Title": {
    "S": "18-Bicycle 301"
  },
  "Description": {
    "S": "301 description"
  },
  "BicycleType": {
    "S": "Road"
  },
  "Brand": {
    "S": "Brand-Company C"
  },
  "Price": {
    "N": "185"
  },
  "Gender": {
    "S": "F"
  },
  "Color": {
    "SS": [
      "Blue",
      "Silver"
    ]
  },
  "ProductCategory": {
    "S": "Bike"
  },
  "InStock": {
    "BOOL": true
  },
  "QuantityOnHand": {
    "N": "3"
  },
  "RelatedItems": {
    "NS": [
      "801",
      "822",
      "979"
    ]
  },
  "Pictures": {
    "L": [
      {
        "M": {
          "FrontView": {
            "S": "http://example/products/301_front.jpg"
          }
        }
      },
      {
        "M": {
          "RearView": {
            "S": "http://example/products/301_rear.jpg"
          }
        }
      },
      {
        "M": {
          "SideView": {
            "S": "http://example/products/301_left_side.jpg"
          }
        }
      }
    ]
  },
  "ProductReviews": {
    "M": {
      "FiveStar": {
        "SS": [
          "My daughter really enjoyed this bike!"
        ]
      },
      "ThreeStar": {
        "SS": [
          "This bike was okay, but I would have preferred it in my color.",
	      "Fun to ride."
        ]
      }
    }
  }
}
```

## Get a Single Item by Using Expressions and the Item’s Primary Key


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.GetItem` method and a set of expressions to get and then print the item that has an `Id` of `205`. Only the following attributes of the item are returned: `Id`, `Title`, `Description`, `Color`, `RelatedItems`, `Pictures`, and `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new GetItemRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, Description, Color, #ri, Pictures, #pr",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#ri", "RelatedItems" }
  },
  Key = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "205" } }
  },
};
var response = client.GetItem(request);

// PrintItem() is a custom function.
PrintItem(response.Item);
```

In the preceding example, the `ProjectionExpression` property specifies the attributes to be returned. The `ExpressionAttributeNames` property specifies the placeholder `#pr` to represent the `ProductReviews` attribute and the placeholder `#ri` to represent the `RelatedItems` attribute. The call to `PrintItem` refers to a custom function as described in [Print an Item](#dynamodb-expressions-print-item).

## Get Multiple Items by Using Expressions and the Table’s Primary Key


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.Query` method and a set of expressions to get and then print the item that has an `Id` of `301`, but only if the value of `Price` is greater than `150`. Only the following attributes of the item are returned: `Id`, `Title`, and all of the `ThreeStar` attributes in `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new QueryRequest
{
  TableName = "ProductCatalog",
  KeyConditions = new Dictionary<string,Condition>
  {
    { "Id", new Condition()
      {
        ComparisonOperator = ComparisonOperator.EQ,
        AttributeValueList = new List<AttributeValue>
        {
          new AttributeValue { N = "301" }
        }
      }
    }
  },
  ProjectionExpression = "Id, Title, #pr.ThreeStar",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#p", "Price" }
  },
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":val", new AttributeValue { N = "150" } }
  },
  FilterExpression = "#p > :val"
};
var response = client.Query(request);

foreach (var item in response.Items)
{
  // Write out the first page of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

In the preceding example, the `ProjectionExpression` property specifies the attributes to be returned. The `ExpressionAttributeNames` property specifies the placeholder `#pr` to represent the `ProductReviews` attribute and the placeholder `#p` to represent the `Price` attribute. `#pr.ThreeStar` specifies to return only the `ThreeStar` attribute. The `ExpressionAttributeValues` property specifies the placeholder `:val` to represent the value `150`. The `FilterExpression` property specifies that `#p` (`Price`) must be greater than `:val` (`150`). The call to `PrintItem` refers to a custom function as described in [Print an Item](#dynamodb-expressions-print-item).

## Get Multiple Items by Using Expressions and Other Item Attributes


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.Scan` method and a set of expressions to get and then print all items that have a `ProductCategory` of `Bike`. Only the following attributes of the item are returned: `Id`, `Title`, and all of the attributes in `ProductReviews`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new ScanRequest
{
  TableName = "ProductCatalog",
  ProjectionExpression = "Id, Title, #pr",
  ExpressionAttributeValues = new Dictionary<string,AttributeValue>
  {
    { ":catg", new AttributeValue { S = "Bike" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#pr", "ProductReviews" },
    { "#pc", "ProductCategory" }
  },
  FilterExpression = "#pc = :catg",  
};
var response = client.Scan(request);

foreach (var item in response.Items)
{
  // Write out the first page/scan of an item's attribute keys and values.
  // PrintItem() is a custom function.
  PrintItem(item);
  Console.WriteLine("=====");
}
```

In the preceding example, the `ProjectionExpression` property specifies the attributes to be returned. The `ExpressionAttributeNames` property specifies the placeholder `#pr` to represent the `ProductReviews` attribute and the placeholder `#pc` to represent the `ProductCategory` attribute. The `ExpressionAttributeValues` property specifies the placeholder `:catg` to represent the value `Bike`. The `FilterExpression` property specifies that `#pc` (`ProductCategory`) must be equal to `:catg` (`Bike`). The call to `PrintItem` refers to a custom function as described in [Print an Item](#dynamodb-expressions-print-item).

## Print an Item


The following example shows how to print an item’s attributes and values. This example is used in the preceding examples that show how to [Get a Single Item by Using Expressions and the Item’s Primary Key](#dynamodb-expressions-get-item), [Get Multiple Items by Using Expressions and the Table’s Primary Key](#dynamodb-expressions-query), and [Get Multiple Items by Using Expressions and Other Item Attributes](#dynamodb-expressions-scan).

```
// using Amazon.DynamoDBv2.Model;

// Writes out an item's attribute keys and values.
public static void PrintItem(Dictionary<string, AttributeValue> attrs)
{
  foreach (KeyValuePair<string, AttributeValue> kvp in attrs)
  {
    Console.Write(kvp.Key + " = ");
    PrintValue(kvp.Value);
  }
}

// Writes out just an attribute's value.
public static void PrintValue(AttributeValue value)
{
  // Binary attribute value.
  if (value.B != null)
  {
    Console.Write("Binary data");
  }
  // Binary set attribute value.
  else if (value.BS.Count > 0)
  {
    foreach (var bValue in value.BS)
    {
      Console.Write("\n  Binary data");
    }
  }
  // List attribute value.
  else if (value.L.Count > 0)
  {
    foreach (AttributeValue attr in value.L)
    {
      PrintValue(attr);
    }
  }
  // Map attribute value.
  else if (value.M.Count > 0)
  {
    Console.Write("\n");
    PrintItem(value.M);
  }
  // Number attribute value.
  else if (value.N != null)
  {
    Console.Write(value.N);
  }
  // Number set attribute value.
  else if (value.NS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.NS.ToArray()));
  }
  // Null attribute value.
  else if (value.NULL)
  {
    Console.Write("Null");
  }
  // String attribute value.
  else if (value.S != null)
  {
    Console.Write(value.S);
  }
  // String set attribute value.
  else if (value.SS.Count > 0)
  {
    Console.Write("{0}", string.Join("\n", value.SS.ToArray()));
  }
  // Otherwise, boolean value.
  else
  {
    Console.Write(value.BOOL);
  }
 
  Console.Write("\n");
}
```

In the preceding example, each attribute value has several data-type-specific properties that can be evaluated to determine the correct format to print the attribute. These properties include `B`, `BOOL`, `BS`, `L`, `M`, `N`, `NS`, `NULL`, `S`, and `SS`, which correspond to those in the [JSON Data Format](DataFormat.html). For properties such as `B`, `N`, `NULL`, and `S`, if the corresponding property is not `null`, then the attribute is of the corresponding non-`null` data type. For properties such as `BS`, `L`, `M`, `NS`, and `SS`, if `Count` is greater than zero, then the attribute is of the corresponding non-zero-value data type. If all of the attribute’s data-type-specific properties are either `null` or the `Count` equals zero, then the attribute corresponds to the `BOOL` data type.

## Create or Replace an Item by Using Expressions


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.PutItem` method and a set of expressions to update the item that has a `Title` of `18-Bicycle 301`. If the item doesn’t already exist, a new item is added.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new PutItemRequest
{
  TableName = "ProductCatalog",
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product", 
  // CreateItemData() is a custom function.
  Item = CreateItemData()
};
client.PutItem(request);
```

In the preceding example, the `ExpressionAttributeNames` property specifies the placeholder `#title` to represent the `Title` attribute. The `ExpressionAttributeValues` property specifies the placeholder `:product` to represent the value `18-Bicycle 301`. The `ConditionExpression` property specifies that `#title` (`Title`) must be equal to `:product` (`18-Bicycle 301`). The call to `CreateItemData` refers to the following custom function:

```
// using Amazon.DynamoDBv2.Model;

// Provides a sample item that can be added to a table.
public static Dictionary<string, AttributeValue> CreateItemData()
{
  var itemData = new Dictionary<string, AttributeValue>
  {
    { "Id", new AttributeValue { N = "301" } },
    { "Title", new AttributeValue { S = "18\" Girl's Bike" } },
    { "BicycleType", new AttributeValue { S = "Road" } },
    { "Brand" , new AttributeValue { S = "Brand-Company C" } },
    { "Color", new AttributeValue { SS = new List<string>{ "Blue", "Silver" } } },
    { "Description", new AttributeValue { S = "301 description" } },
    { "Gender", new AttributeValue { S = "F" } },
    { "InStock", new AttributeValue { BOOL = true } },
    { "Pictures", new AttributeValue { L = new List<AttributeValue>{ 
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "FrontView", new AttributeValue { S = "http://example/products/301_front.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "RearView", new AttributeValue {S = "http://example/products/301_rear.jpg" } } } } },
      { new AttributeValue { M = new Dictionary<string,AttributeValue>{
        { "SideView", new AttributeValue { S = "http://example/products/301_left_side.jpg" } } } } }
    } } },
    { "Price", new AttributeValue { N = "185" } },
    { "ProductCategory", new AttributeValue { S = "Bike" } },
    { "ProductReviews", new AttributeValue { M = new Dictionary<string,AttributeValue>{
      { "FiveStar", new AttributeValue { SS = new List<string>{
        "My daughter really enjoyed this bike!" } } },
      { "OneStar", new AttributeValue { SS = new List<string>{
        "Fun to ride.",
        "This bike was okay, but I would have preferred it in my color." } } }
    } } },
    { "QuantityOnHand", new AttributeValue { N = "3" } },
    { "RelatedItems", new AttributeValue { NS = new List<string>{ "979", "822", "801" } } }
  };

  return itemData;
}
```

In the preceding example, an example item with sample data is returned to the caller. A series of attributes and corresponding values are constructed, using data types such as `BOOL`, `L`, `M`, `N`, `NS`, `S`, and `SS`, which correspond to those in the [JSON Data Format](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/DataFormat.html).

## Update an Item by Using Expressions


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.UpdateItem` method and a set of expressions to change the `Title` to `18" Girl's Bike` for the item with `Id` of `301`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new UpdateItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":newproduct", new AttributeValue { S = "18\" Girl's Bike" } }
  },
  UpdateExpression = "SET #title = :newproduct"
};
client.UpdateItem(request);
```

In the preceding example, the `ExpressionAttributeNames` property specifies the placeholder `#title` to represent the `Title` attribute. The `ExpressionAttributeValues` property specifies the placeholder `:newproduct` to represent the value `18" Girl's Bike`. The `UpdateExpression` property specifies to change `#title` (`Title`) to `:newproduct` (`18" Girl's Bike`).

## Delete an Item by Using Expressions


The following example features the `Amazon.DynamoDBv2.AmazonDynamoDBClient.DeleteItem` method and a set of expressions to delete the item with `Id` of `301`, but only if the item’s `Title` is `18-Bicycle 301`.

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.Model;

var client = new AmazonDynamoDBClient();
var request = new DeleteItemRequest
{
  TableName = "ProductCatalog",
  Key = new Dictionary<string,AttributeValue>
  {
     { "Id", new AttributeValue { N = "301" } }
  },
  ExpressionAttributeNames = new Dictionary<string, string>
  {
    { "#title", "Title" }
  },
  ExpressionAttributeValues = new Dictionary<string, AttributeValue>
  {
    { ":product", new AttributeValue { S = "18-Bicycle 301" } }
  },
  ConditionExpression = "#title = :product"
};
client.DeleteItem(request);
```

In the preceding example, the `ExpressionAttributeNames` property specifies the placeholder `#title` to represent the `Title` attribute. The `ExpressionAttributeValues` property specifies the placeholder `:product` to represent the value `18-Bicycle 301`. The `ConditionExpression` property specifies that `#title` (`Title`) must equal `:product` (`18-Bicycle 301`).

## More Info


For more information and code examples, see:
+  [DynamoDB Series - Expressions](http://blogs.aws.amazon.com/net/post/TxZQM7VA9AUZ9L/DynamoDB-Series-Expressions) 
+  [Accessing Item Attributes with Projection Expressions](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/Expressions.AccessingItemAttributes.html) 
+  [Using Placeholders for Attribute Names and Values](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/ExpressionPlaceholders.html) 
+  [Specifying Conditions with Condition Expressions](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/Expressions.SpecifyingConditions.html) 
+  [Modifying Items and Attributes with Update Expressions](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/Expressions.Modifying.html) 
+  [Working with Items Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetItemCRUD.html) 
+  [Querying Tables Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetQuerying.html) 
+  [Scanning Tables Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LowLevelDotNetScanning.html) 
+  [Working with Local Secondary Indexes Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/LSILowLevelDotNet.html) 
+  [Working with Global Secondary Indexes Using the Amazon SDK for .NET Low-Level API](https://docs.amazonaws.cn/amazondynamodb/latest/developerguide/GSILowLevelDotNet.html) 

# JSON support in Amazon DynamoDB
JSON support

**Note**  
The information in this topic is specific to projects based on .NET Framework and the Amazon SDK for .NET version 3.3 and earlier.

The Amazon SDK for .NET supports JSON data when working with Amazon DynamoDB. This enables you to more easily get JSON-formatted data from, and insert JSON documents into, DynamoDB tables.

**Topics**
+ [

## Get Data from a DynamoDB Table in JSON Format
](#dynamodb-json-get-table-data)
+ [

## Insert JSON Format Data into a DynamoDB Table
](#dynamodb-json-insert-table-data)
+ [

## DynamoDB Data Type Conversions to JSON
](#dynamodb-json-datatypes)
+ [

## More Info
](#dynamodb-json-more-info)

## Get Data from a DynamoDB Table in JSON Format


The following example shows how to get data from a DynamoDB table in JSON format:

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var item = table.GetItem(3, "Horse");

var jsonText = item.ToJson();
Console.Write(jsonText);
      
// Output:
//   {"Name":"Shadow","Type":"Horse","Id":3}

var jsonPrettyText = item.ToJsonPretty();
Console.WriteLine(jsonPrettyText);
      
// Output:
//   {
//     "Name" : "Shadow",
//     "Type" : "Horse",
//     "Id"   : 3
//   }
```

In the preceding example, the `ToJson` method of the `Document` class converts an item from the table into a JSON-formatted string. The item is retrieved through the `GetItem` method of the `Table` class. To determine the item to get, in this example, the `GetItem` method uses the hash-and-range primary key of the target item. To determine the table to get the item from, the `LoadTable` method of the `Table` class uses an instance of the `AmazonDynamoDBClient` class and the name of the target table in DynamoDB.

## Insert JSON Format Data into a DynamoDB Table


The following example shows how to use JSON format to insert an item into a DynamoDB table:

```
// using Amazon.DynamoDBv2;
// using Amazon.DynamoDBv2.DocumentModel;

var client = new AmazonDynamoDBClient();
var table = Table.LoadTable(client, "AnimalsInventory");
var jsonText = "{\"Id\":6,\"Type\":\"Bird\",\"Name\":\"Tweety\"}";
var item = Document.FromJson(jsonText);

table.PutItem(item);
```

In the preceding example, the `FromJson` method of the `Document` class converts a JSON-formatted string into an item. The item is inserted into the table through the `PutItem` method of the `Table` class, which uses the instance of the `Document` class that contains the item. To determine the table to insert the item into, the `LoadTable` method of the `Table` class is called, specifying an instance of the `AmazonDynamoDBClient` class and the name of the target table in DynamoDB.

## DynamoDB Data Type Conversions to JSON


Whenever you call the `ToJson` method of the `Document` class, and then on the resulting JSON data you call the `FromJson` method to convert the JSON data back into an instance of a `Document` class, some DynamoDB data types will not be converted as expected. Specifically:
+ DynamoDB sets (the `SS`, `NS`, and `BS` types) will be converted to JSON arrays.
+ DynamoDB binary scalars and sets (the `B` and `BS` types) will be converted to base64-encoded JSON strings or lists of strings.

  In this scenario, you must call the `DecodeBase64Attributes` method of the `Document` class to replace the base64-encoded JSON data with the correct binary representation. The following example replaces a base64-encoded binary scalar item attribute in an instance of a `Document` class, named `Picture`, with the correct binary representation. This example also does the same for a base64-encoded binary set item attribute in the same instance of the `Document` class, named `RelatedPictures`:

  ```
  item.DecodeBase64Attributes("Picture", "RelatedPictures");
  ```

## More Info


For more information and examples of programming JSON with DynamoDB with the Amazon SDK for .NET, see:
+  [DynamoDB JSON Support](https://aws.amazon.com/blogs/developer/dynamodb-json-support/) 
+  [Amazon DynamoDB Update - JSON, Expanded Free Tier, Flexible Scaling, Larger Items](https://aws.amazon.com/blogs/aws/dynamodb-update-json-and-more/) 