DynamoDb, Reading and Writing Data with .Net Core – Part 2

Want to learn more about AWS Lambda and .NET? Check out my A Cloud Guru course on ASP.NET Web API and Lambda.

Full source code available here.

A few weeks ago I posted about reading and writing data to DynamoDb. I gave instructions on how to get create tables on localstack and how to use the AWS Document Model approach. I also pointed out that I was not a big fan of this, reading data looks like –

1[HttpGet("{personId}")]
2public async Task<IActionResult> Get(int personId)
3{
4    Table people = Table.LoadTable(_amazonDynamoDbClient, "People");
5    var person = JsonSerializer.Deserialize<Person> ((await people.GetItemAsync(personId)).ToJson());
6    return Ok(person);
7}

You have to cast to Json, then deserialize, I think you should be able to do something more like – people.GetItemAsync(personId), but you can’t

And writing data looked like –

 1[HttpPost]
 2public async Task<IActionResult> Post(Person person)
 3{
 4    Table people = Table.LoadTable(_amazonDynamoDbClient, "People");
 5     
 6    var document = new Document();
 7    document["PersonId"] = person.PersonId;
 8    document["State"] = person.State;
 9    document["FirstName"] = person.FirstName;
10    document["LastName"] = person.LastName;
11    await people.PutItemAsync(document);
12     
13    return Created("", document.ToJson());
14}

For me this feels even worse, having to name the keys in the document, very error prone.

Luckily there is another approach that is a little better. You have to create a class with attributes that indicate what table the class represents, and what properties represent the keys in the table.

 1using Amazon.DynamoDBv2.DataModel;
 2 
 3namespace DynamoDbApiObjectApproach.Models
 4{
 5     
 6    [DynamoDBTable("People")]
 7    public class PersonDynamoDb
 8    {
 9 
10        [DynamoDBHashKey]
11        public int PersonId {get;set;}
12        public string State {get;set;}
13        public string FirstName {get;set;}
14        public string LastName {get;set;}
15    }
16}

Because of these attributes, I don’t want to expose this class too broadly, so I create a simple POCO to represent a person.

1public class Person
2{
3    public int PersonId {get;set;}
4    public string State {get;set;}
5    public string FirstName {get;set;}
6    public string LastName {get;set;}
7}

I use AutoMapper to map between the two classes, never exposing the PersonDynamoDb to the outside world. If you need help getting started with AutoMapper I wrote a couple of posts on this recently.

Here’s how reading and writing looks now –

 1[HttpGet("{personId}")]
 2public async Task<IActionResult> Get(int personId)
 3{
 4    var personDynamoDb = await _dynamoDBContext.LoadAsync<PersonDynamoDb>(personId);
 5    var person = _mapper.Map<Person>(personDynamoDb);
 6    return Ok(person);
 7}
 8 
 9[HttpPost]
10public async Task<IActionResult> Post(Person person)
11{
12    var personDynamoDb = _mapper.Map<PersonDynamoDb>(person);
13    await _dynamoDBContext.SaveAsync(personDynamoDb);
14    return Created("", person.PersonId);
15}

This is an improvement, but still not thrilled with the .NET SDK for DynamoDb.

Full source code available here.

comments powered by Disqus

Related