Zoo 105 Podcast: adding CosmosDB

After having developed the first version of the podcast feed, I wanted to improve it. My idea was to cache the data already got from the http endpoint, to achieve two goals:
- improve performances;
- avoid that with an increasing number of users using my podcast feed, I (my podcast) would do many requests to the http endpoint.
As a caching mechanism I've chosen to use CosmosDB, a NoSQL database that has the big advantage of paying for use, completely in line with the Azure Functions mindset.
To use CosmosDB in a .NET Core application, first of all you need to include the Microsoft.Azure.DocumentDB.Core NuGet package.
The data is organized in Databases, Collections (equivalent to a SQL tables) and Documents (equivalent to SQL records). Documents are json files, serialized/deserialized to/from POCO entities with Json.Net.
This is reflected about how to create a Collection (if not existing) and return a DocumentClient:
public static async Task<DocumentClient> GetCosmosDBClientAsync(IConfiguration config)
{
Uri cosmosDBEndpointUri = new Uri(config["CosmosDBEndpointUrl"]);
string cosmosDBPrimaryKey = config["CosmosDBPrimaryKey"];
DocumentClient cosmosDBClient = new DocumentClient(cosmosDBEndpointUri, cosmosDBPrimaryKey);
await cosmosDBClient.CreateDatabaseIfNotExistsAsync(new Database { Id = dbName });
await cosmosDBClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(dbName), new DocumentCollection { Id = collectionName });
return cosmosDBClient;
}
After you have a DocumentClient, you can call its methods to get,
var tempResult = await cosmosDBClient.ReadDocumentAsync(UriFactory.CreateDocumentUri(dbName, collectionName, podcastId));
PodcastEpisode result = (dynamic)tempResult.Resource;
save,
Uri documentCollectionUri = UriFactory.CreateDocumentCollectionUri(dbName, collectionName);
await cosmosDBClient.CreateDocumentAsync(documentCollectionUri, episode);
and update documents:
Uri documentUri = UriFactory.CreateDocumentUri(dbName, collectionName, episode.Id);
await cosmosDBClient.ReplaceDocumentAsync(documentUri, episode);
About the POCO entities: if you don't want that CosmosDB assigns them a GUID id, then they need to have an "id" property (all in lower case). If you want to use the usual C# naming conventions, you can use tag your property with JsonProperty:
public class PodcastEpisode
{
// Id of the podcast, in format yyyyMMdd
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
public DateTime DateUtc { get; set; }
public string FileName { get; set; }
public Uri CompleteUri { get; set; }
public long FileLength { get; set; }
}
When deploying the solution in Azure, you need to create the CosmosDB instance with API: SQL
The source code for this step is available in the dedicated GitHub repository, under the tag 2.CosmosDB.