Daniel Donbavand

Documenting my Development Journey

Creating an AWS DynamoDB Table in .NET Core - Part 1

Amazon Web Services (AWS) is a cloud services platform, they offer compute power, database storage, content delivery and other functionality that help users build and host infranstatuce.

This blog post is the first part of a series where I will go through how to interact with different components that AWS offer.

The first part of the series will look at DynamoDB, this series will also be broken into separate parts so each blog post will focus on one or two pieces of functionality from each feature.

In this blog we will be looking at creating a DynamoDB client, then using that client to create a DynamoDB Table.

What is DynamoDB

DynamoDB is a fully managed NoSQL database, that provides fast performance, the data is stored on a solid state drive, this gives a predictable performance. DynamoDB is scalable, meaning that it can be scaled either up or down as needed.

Rather than purchasing storage, when you create a table you specify a provisioned throughput. Throughput is the amount of read and write activity that the table will be able to support.

Setting up an AWS Account.

In order to interact with AWS components and features, we first need to create an AWS account.

If you are unsure on how to do this, there is a great tutorial by AWS. This takes you through the steps needed to create an account.

Creating an Amazon Web Services Account

It is worth pointing out, that AWS offer free tier services for the first year.

Creating a Project

Let's get started by creating a simple .NET Core 2.0 Web API. I will be using this dummy project as a way to show the code needed to create the AWS DynamoDB client and then how to use the client to create the DynamoDB table.

For detailed instructions on how to create a simple Web API, head along to my YouTube tutorial ASP.NET Core 2.0: Building a Simple Web API

Create the client

In order to be able to interact with any AWS service, we need to create and setup a client. Our client will contain the following information, AWS region, AccessKey and SecretKey. This is the minimum information we need to interact with DynamoDB.

While there are a few ways to create the client, we will be setting it up using .NET Cores 2.0 Dependency Injection.

We first need to install the following two nuget package

AWSSDK.Extensions.NETCore.Setup
AWSSDK.DynamoDBv2 

Once we have our NuGet packages installed, we can then add the following to our ConfigureServices method inside the startup.cs file. This will allow us to dependency inject the IAmazonDynamoDB client into the classes that need to interact with it.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
    services.AddAWSService<IAmazonDynamoDB>();
}

Let’s create a class that will implement the client that will be used to create the DynamoDB table. You can also create DynamoDB tables by logging into the AWS console and manually creating it.

Let’s look at how we would create the table in code.

Setting Credentials

As mentioned above, in order to interact with DynamoDB or any other service in AWS, we need our credentials loaded into our client.

When we installed the AWSSDK.Extensions.NETCore.Setup NuGet package, this allows us to use the following method

services.AddDefaultAWSOptions(Configuration.GetAWSOptions()). 

This attempts to get the AWS options that have been set.

The startup.cs ConfigureServices method would look something like this.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
    services.AddAWSService<IAmazonDynamoDB>();
}

Note: In order to read from and use the Configuration.GetAWSOptions() you need to setup an IConfiguration in the startup class. Add the following code to the startup.cs constructor.

public Startup()
{
    Configuration = new ConfigurationBuilder()
        .SetBasePath(Directory.GetCurrentDirectory())
        .AddJsonFile("appsettings.json")
        .Build();
}

then add the following property below the constructor.

public IConfigurationRoot Configuration { get; set; }

Once we have our "AddDefaultAWSOptions()" set, this will first look for the credentials inside the .aws folder, that is stored in your user profile on your drive. For example on my computer it is store in the following location "C:\Users\username.aws" the filename where the credentials are store is "credentials" below is an example of what the credentials file looks like.

[default]
aws_access_key_id = xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
aws_secret_access_key =xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
toolkit_artifact_guid=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Another option instead of using the credentials file would be to store them in the appsettings.json file.

This isn’t the normal way of doing things, when storing keys inside our application, we run the risk of exposing these to the outside world, by accidentally pushing them up to your repository.

Below is a bit of a hack, but it's a way to use the credentials in your appsettings.json if that is what you are after. Add the following Environment.SetEnvironmentVariable to the ConfigureServices inside the startup.cs file.

HACK

public void ConfigureServices(IServiceCollection services)
{
    Environment.SetEnvironmentVariable("AWS_ACCESS_KEY_ID", Configuration["AWS:AccessKey"]);
    Environment.SetEnvironmentVariable("AWS_SECRET_ACCESS_KEY", Configuration["AWS:SecretKey"]);
    Environment.SetEnvironmentVariable("AWS_REGION", Configuration["AWS:Region"]);
}

Appsettings.json

The appsettings.json file is not added to your solution by default, you will need to add the file to your solution.

This is what my appsetting.json file looks like

{
    "AWS": {
        "Region": "us-east-1",
        "AccessKey": "xxxxxxxxxxxxxxxxxxxxxxxxx",
        "SecretKey": "xxxxxxxxxxxxxxxxxxxxxxxxx"
       }
}

DynamoDBController

Now that we have our client setup. We can start to create the controller that we are going to use to create a DynamoDB table.

Note: I am using a Web API to show how we can write code that will allow us to create a table, but you can add the CreateDynamoDbTable() method to any .NET Core application.

Let's create a DynamoDB Controller. Our controller will have the following endpoint
api/DynamoDb/createtable and it will call off to a ICreateTable interface. We will create the logic of adding the DynamoDB table inside the CreateTable class.

namespace DynamoDb.Controllers
{
    [Route("api/DynamoDb")]
    public class DynamoDbController : Controller
    {
        private readonly ICreateTable _createTable;

        public DynamoDbController(ICreateTable createTable)
        {
	        _createTable = createTable;
        }

        [Route("createtable")]
        public IActionResult CreateDynamoDbTable()
        {
            _createTable.CreateDynamoDbTable();

            return Ok();
        }
    }
}

In the above example, I have created an interface ICreateTable and a class CreateTable.

We need to make sure those are initialize inside our startup.cs file

services.AddSingleton<ICreateTable, CreateTable>();

So our ConfigureServices now looks like this.

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddDefaultAWSOptions(Configuration.GetAWSOptions());
    services.AddAWSService<IAmazonDynamoDB>();
    services.AddSingleton<ICreateTable, CreateTable>();
}

Once we have our tables set and bound ICreateTable to CreateTable in ConfigureServices we write the code that will actually create the Dynamo table, using the .NET DynamoDB SDK

private readonly IAmazonDynamoDB _dynamoDbClient;
private static readonly string tableName = "TempDynamoDbTable";

public CreateTable(IAmazonDynamoDB dynamoDbClient)
{
    _dynamoDbClient = dynamoDbClient;
}

public void CreateDynamoDbTable()
{
    try
    {
        CreateTempTable();
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }
}
private void CreateTempTable()
{
    Console.WriteLine("Creating Table");

    var request = new CreateTableRequest
    {
        AttributeDefinitions = new List<AttributeDefinition>
        {
            new AttributeDefinition
            {
                AttributeName = "Id",
                AttributeType = "N"
            },
            new AttributeDefinition
            {
                AttributeName = "ReplyDateTime",
                AttributeType = "N"
            }
        },
        KeySchema = new List<KeySchemaElement>
        {
            new KeySchemaElement
            {
                AttributeName = "Id",
                KeyType = "HASH" // Partition Key
            },
            new KeySchemaElement
            {
                AttributeName = "ReplyDateTime",
                KeyType = "Range" // Sort Key
            }
        },
        ProvisionedThroughput = new ProvisionedThroughput
        {
            ReadCapacityUnits = 5,
            WriteCapacityUnits = 5
        },
        TableName = tableName
    };

    var response = _dynamoDbClient.CreateTableAsync(request);

    WaitUntilTableReady(tableName);
}

We also want to create something to check and wait for the DynamoDB table to be created.

The Dynamo table will take a little while to create, without checking that the table is created, if we were to execute another action, we would be returned an error, as the table would not yet exist.

public void WaitUntilTableReady(string tableName)
{
    string status = null;

    do
    {
        Thread.Sleep(5000);
        try
        {
            var res = _dynamoDbClient.DescribeTableAsync(new DescribeTableRequest
            {
                TableName = tableName
            });

            status = res.Result.Table.TableStatus;
        }
        catch (ResourceNotFoundException)
        {
          
        }
        
    } while (status != "ACTIVE");
    {
        Console.WriteLine("Table Created Successfully");
    }
}

That's it, we now have the code that will allow us to create a DynamoDB Table in AWS.

Summary

To summarize we created a simple .NET Core Web API with an endpoint that when hit, will create us a DynamoDB Table. The DynamoDB table name is hard coded in this example, but if we wanted we could have added a query to our endpoint, that would allow us to enter a table name defined by the user interacting with our endpoint.

I'm using a Web API to show you a way to create a DynamoDB table, this is only an example, it's very likely that you wouldn't actually want to setup an endpoint to create a DynamoDB table. You should be able to copy and paste the code above and add it to your project where it makes sense.

Coming up in the next blog post we look at "putting items" onto our newly created DynamoDB table.

Helpful links

.NET Code Samples

Configuring AWS SDK with .NET Core