Getting Started with DocumentDb and C# .NET

PUBLISHED ON JAN 19, 2017 — .NET, AZURE, DATABASES

One of the things I’ve been playing around with recently is an Azure hosted DocumentDb - coincidentally it’s also my first foray into NoSQL databases!

In this post I’ll be covering the basics of getting up and running with DocumentDb based on what I’ve encountered so far. To do this, we’re going to use a basic Console application, and through this we’ll create and read a new database, document collection, and documents themselves.

First, we need to make sure everything is set up in Azure (you’ll need an Azure account with some credit available for this - if you have an MSDN subscription, you get £40 free credit a month (or your local equivalence 🙂 )

In the Azure portal click the + New button, and in the pane that appears select Databases and then NoSQL (DocumentDb)

In the New account pane that loads, give your account an ID, a new Resource Group name, and select the Location.

Once done, click Create, and wait for the database to be deployed.

While waiting for the deployment, open Visual Studio and create a blank Console Application. Open the Nuget package manager so we can add DocumentDb - searching documentdb should find it as the top result, titled Microsoft.Azure.DocumentDB

Now in your Program class, create two const strings. These will be used to hold the endpoint URI and the Primary Key of the DocumentDb account.

Now that the database has been deployed, we need to get the endpoint URI and the Primary Key for the account. To do this, navigate to your DocumentDb account and select Keys. From here copy the URI and Primary Key values into the strings in your console application.

We’ll also want to add an instance of DocumentClient to the class as well, which is the client used for interaction with the database, so your class should look something like this:

class Program
{
	private const string ENDPOINT_URI = "<your-endpoint>";
	private const string PRIMARY_KEY = "<your-primary-key>";
	private static DocumentClient _client;
	
	static void Main(string[] args){
	
	}
}

Now, we need to create a new instance of DocumentClient using the endpoint and primary key:

try
{
	_client = new DocumentClient(new Uri(ENDPOINT_URI), PRIMARY_KEY);
}
catch (Exception ex)
{
	Console.WriteLine(ex.Message);
}

This will try and connect to your AzureDb account, and write out the error if it fails.

Now we want to actually create a Database on our account, but we also need to account for the database already existing. The official docs tell you to attempt to read the database immediately in a try-catch block, creating the database in the catch block if the status code indicates it wasn’t found.

Personally, I hate this approach - I’m a firm believer that exception handling should never be used to control program flow.

Instead, for this example, we’ll query for the database first, and create the database if that doesn’t exist:

if (!_client.CreateDatabaseQuery().Where(db => db.Id == _databaseName).AsEnumerable().Any())
{
	await _client.CreateDatabaseAsync(new Database { Id = _databaseName });
}

Here we’re querying for a database with an id matching the chosen name for your database - which I’ve stored in a private field. If any are found matching, we do nothing, otherwise we create a new database through the client, setting the name.

Now we have our database, we need a Document Collection for us to store our items. Again, the Microsoft article shows this done using a try-catch block. Instead, I’ve used another query, this time based on the collection name we want to use:

if (!_client.CreateDocumentCollectionQuery(UriFactory.CreateDatabaseUri(_databaseName))
	.Where(col1 => col1.Id == _collectionName).ToArray()
	.Any())
{
	DocumentCollection collectionInfo = new DocumentCollection();
	collectionInfo.Id = _collectionName;
	await _client.CreateDocumentCollectionAsync(UriFactory.CreateDatabaseUri(_databaseName), 
										collectionInfo,
										New RequestOptions { OfferThroughput = 400 });
}

Again, we query to see if a document collection with an id matching our given name already exists. If it does, do nothing, otherwise we create a new document collection object, set the id to our chosen name (which I’ve also set to a private field for future use), and then we pass that to the client alongside the URI for our database, and a RequestOptions object. For the RequestOptions I’ve simply set the throughput to 400 for the collection - this is the lowest option available, and thus the cheapest.

Now we have our database and document collection, the last step is to write to our database. The method on the client accepts any object, as NoSQL makes no demands on what is being written to the database adhering to any set schema.

So given an object documentObject we can write to the database like this:

await _client.CreateDocumentAsnc(UriFactory(CreateDocumentCollectionUri(_databaseName, _collectionName),
										documentObject);

Reading from the database is achieved in a similar fashion:

await _client.ReadDocumentAsync(UriFactory.CreateDocumentUri(databaseName, collectionName, documentId));

The documentId parameter is the id of the document you’re wanting to retrieve. If you want to keep track of the id properties of documents yourself, you can set an id property on the object you write to the property. Note that this must be lowercase, which threw me off when I first attempted this! Personally, I keep track of the id by creating a Guid for each object before writing to the database. Of course, there are other ways of querying for documents which I may cover in the future.

But that’s all that’s needed to get up and running with the basics - you now have a database, a document collection, and can read and write documents to that collection! If anything is unclear, or you spot anything I could improve, please let me know!

TAGS: .NET, AZURE, C#, DATABASES
comments powered by Disqus