Adventuring into the Cosmos

Photo by Greg Rakozy on Unsplash

Adventuring into the Cosmos

Trying out Azure Cosmos DB

Studying for AZ-204: Developing Solutions for Microsoft Azure

I'm scheduled to take the AZ-204 exam in the next couple of weeks so I'm currently playing around with the main resources covered to get some practice in the portal and also writing client code to use the resources.

Today I'm having a go at creating a NoSQL database in Cosmos and creating a client repository in C# to use the Cosmos DB as a document datastore for a simple Web API app. The API enables clients to store information about pens and ink in them. Being a pen geek I find this a really simple example data and functionality to play about with.

The GitHub repo for the WebAPI can be found here

Creating a Cosmos DB Account

Creating a Cosmos DB is really simple. Having just finished an MSc in Computer Science with the OU, I have a student account with Azure and get free credits, but there is a free tier of Cosmos DB so anybody can play around with it at no cost.

To create the Cosmos DB, I just went to the portal, searched for Cosmos and then clicked Create...

Screenshot 2022-04-15 at 16.44.35.png

I then clicked Create on the recommended Core SQL Cosmos DB...

Screenshot 2022-04-15 at 16.44.45.png

The only things I set when configuring the new Cosmos DB to create were on the first "Basics" tab:

  • I created a new resource group
  • Gave the instance an account name
  • The free tier was already enabled by default, but worth checking!
  • Click the Review + Create button

Screenshot 2022-04-15 at 16.46.56.png

Creating a Cosmos DB Container

It will take a few minutes for the Cosmos DB to be deployed. Once it is, when you go into it the "Quick Start" blade will be open by default. If you close the portal and go back into it, you can get back to it by clicking "Quick Start" on the left menu.

I left ".NET" selected for the platform as I will be writing client code in .NET later. I then clicked the "Create 'Items' Container" button...

Screenshot 2022-04-15 at 17.14.30.png

I then clicked the "Downloads" button to download the sample .NET client code...

Screenshot 2022-04-15 at 17.23.28.png

The Quick Start "Create 'Items' Container" button created a database called ToDoList and a container called Items which looked like this...

Screenshot 2022-04-15 at 17.27.04.png

This wasn't what I wanted so I deleted the ToDoList database and created a one called InkedUp...

Screenshot 2022-04-15 at 17.31.25.png

Then I created a container called EventStreams as my app uses EventSourcing so will store an EventStream for each Entity. I set the Partition Key to "/OwnerId" as that is a property on my Entities such as Pens that should create quite an even distribution. I set the ID of the container to be Id which must be unique per partition.

Screenshot 2022-04-15 at 19.50.31.png

Creating Client Code

The sample client code previously downloaded contained two code files... one that contained a POCO (Plain Old C# Object) called Family that can be easily serialised to JSON. The other file has a lot of client code examples to set up a Cosmos DB Client and perform CRUD operations on it using the Family object as the item in the DB. This was a good starting point for me to begin creating client code for my example app.

To start updating my own project, I added a NuGet Package Reference to Microsoft.Azure.Cosmos...

Screenshot 2022-04-15 at 18.54.34.png

EventStream Item

I created this EventStream class which will represent a row in the Cosmos DB. Note the JsonProperty attribute on the Id member to make the serialised property match the lowercase id that the item will have in the Cosmos DB. The OwnerId property will be the Partition Key in the Cosmos DB.


For each event in the stream I store the serialised event data as a string and the fully qualified event class name as the type so that I can deserialise events and handle them in a generic way.


PenCosmosRepository Class

I created this repository based on the example code in the sample project downloaded from the Azure Portal. The portal is used to save an EventStream for an entity with an Id and an OwnerId. The EventStream can also be updated and loaded from the Cosmos DB. Note that this is very much a "Hello World" Cosmos DB Repository class and probably doesn't follow best practices in terms of key storage, most efficient use of a Cosmos DB Connection etc.

The current code can be found in GitHub here

image.png image.png image.png image.png image.png

Items in Cosmos DB

This is what items look like in Cosmos DB, which you can get to by going to "Data Explorer" within your Cosmos DB in the Azure Portal. Click on Items to see a list of items in the Cosmos DB Container. You can then click on an individual item to view the json document.

Screenshot 2022-04-17 at 15.07.54.png

What's Next?

I still have more to do in the API... I've added a Get to the Command so I can test that Event Streams are being persisted and loaded correctly in the right order. Next steps are to implement Queries and look at persisting Read Models optimised for the reads. I might try playing with Azure Table Storage for those.

Also, while the Cosmos DB Repository is working to persist and load data, it could probably be refactored. I'm using Create and Replace for creating and updating items, checking if the item exists first then calling the correct method accordingly. I think that could all be replaced with an Upsert.

If anybody is keen to find more about the implementation of EventSourcing and CQRS that I'm following for my repo, it's largely based on "Hands-On Domain-Driven Design with .NET Core: Tackling complexity in the heart of software by putting DDD principles into practice" by Alexey Zimarev, which I'd highly recommend reading.