Full source code available here.
A few weeks ago I posted about reading and writing data to DynamoDb. I gave instruction 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 look like –
[HttpGet("{personId}")] public async Task<IActionResult> Get(int personId) { Table people = Table.LoadTable(_amazonDynamoDbClient, "People"); var person = JsonSerializer.Deserialize<Person> ((await people.GetItemAsync(personId)).ToJson()); return Ok(person); }
You have to cast to JSON, then deserialize, I think you should be able be able to do something more like – people.GetItemAsync
, but you can’t
And writing data looked like –
[HttpPost] public async Task<IActionResult> Post(Person person) { Table people = Table.LoadTable(_amazonDynamoDbClient, "People"); var document = new Document(); document["PersonId"] = person.PersonId; document["State"] = person.State; document["FirstName"] = person.FirstName; document["LastName"] = person.LastName; await people.PutItemAsync(document); return Created("", document.ToJson()); }
For me this feels even worse, having to name the keys in the document, very error prone and hard.
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.
using Amazon.DynamoDBv2.DataModel; namespace DynamoDbApiObjectApproach.Models { [DynamoDBTable("People")] public class PersonDynamoDb { [DynamoDBHashKey] public int PersonId {get;set;} public string State {get;set;} public string FirstName {get;set;} public string LastName {get;set;} } }
Because of these attributes I don’t want to expose this class too broadly, so I create a simple POCO to represent a person.
public class Person { public int PersonId {get;set;} public string State {get;set;} public string FirstName {get;set;} public string LastName {get;set;} }
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 recently on this.
Here’s how reading and writing looks now –
[HttpGet("{personId}")] public async Task<IActionResult> Get(int personId) { var personDynamoDb = await _dynamoDBContext.LoadAsync<PersonDynamoDb>(personId); var person = _mapper.Map<Person>(personDynamoDb); return Ok(person); } [HttpPost] public async Task<IActionResult> Post(Person person) { var personDynamoDb = _mapper.Map<PersonDynamoDb>(person); await _dynamoDBContext.SaveAsync(personDynamoDb); return Created("", person.PersonId); }
This is an improvement, but still not thrilled with the .NET SDK for DynamoDb.
Full source code available here.