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.