title | description | keywords | services | documentationcenter | author | manager | editor | ms.assetid | ms.service | ms.workload | ms.tgt_pltfrm | ms.devlang | ms.topic | ms.date | ms.author |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
NoSQL tutorial: DocumentDB .NET SDK | Microsoft Docs |
A NoSQL tutorial that creates an online database and C# console application using the DocumentDB .NET SDK. DocumentDB is a NoSQL database for JSON. |
nosql tutorial, online database, c# console application |
documentdb |
.net |
AndrewHoh |
jhubbard |
monicar |
bf08e031-718a-4a2a-89d6-91e12ff8797d |
documentdb |
data-services |
na |
dotnet |
hero-article |
12/16/2016 |
anhoh |
[!div class="op_single_selector"]
Welcome to the NoSQL tutorial for the Azure DocumentDB .NET SDK! After following this tutorial, you'll have a console application that creates and queries DocumentDB resources.
We'll cover:
- Creating and connecting to a DocumentDB account
- Configuring your Visual Studio Solution
- Creating an online database
- Creating a collection
- Creating JSON documents
- Querying the collection
- Replacing a document
- Deleting a document
- Deleting the database
Don't have time? Don't worry! The complete solution is available on GitHub. Jump to the Get the complete NoSQL tutorial solution section for quick instructions.
Afterwards, please use the voting buttons at the top or bottom of this page to give us feedback. If you'd like us to contact you directly, feel free to include your email address in your comments.
Now let's get started!
Please make sure you have the following:
- An active Azure account. If you don't have one, you can sign up for a free account.
- Alternatively, you can use the Azure DocumentDB Emulator for this tutorial.
- Visual Studio 2013 / Visual Studio 2015.
- .NET Framework 4.6
Let's create a DocumentDB account. If you already have an account you want to use, you can skip ahead to Setup your Visual Studio Solution. If you are using the DocumentDB Emulator, please follow the steps at Azure DocumentDB Emulator to setup the emulator and skip ahead to Setup your Visual Studio Solution.
[!INCLUDE documentdb-create-dbaccount]
-
Open Visual Studio 2015 on your computer.
-
On the File menu, select New, and then choose Project.
-
In the New Project dialog, select Templates / Visual C# / Console Application, name your project, and then click OK.
-
In the Solution Explorer, right click on your new console application, which is under your Visual Studio solution, and then click Manage NuGet Packages...
-
In the Nuget tab, click Browse, and type azure documentdb in the search box.
-
Within the results, find Microsoft.Azure.DocumentDB and click Install. The package ID for the DocumentDB Client Library is Microsoft.Azure.DocumentDB.
If you get a messages about reviewing changes to the solution, click OK. If you get a message about license acceptance, click I accept.
Great! Now that we finished the setup, let's start writing some code. You can find a completed code project of this tutorial at GitHub.
First, add these references to the beginning of your C# application, in the Program.cs file:
using System;
using System.Linq;
using System.Threading.Tasks;
// ADD THIS PART TO YOUR CODE
using System.Net;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using Newtonsoft.Json;
Important
In order to complete this NoSQL tutorial, make sure you add the dependencies above.
Now, add these two constants and your client variable underneath your public class Program.
public class Program
{
// ADD THIS PART TO YOUR CODE
private const string EndpointUri = "<your endpoint URI>";
private const string PrimaryKey = "<your key>";
private DocumentClient client;
Next, head back to the Azure Portal to retrieve your URI and primary key. The DocumentDB URI and primary key are necessary for your application to understand where to connect to, and for DocumentDB to trust your application's connection.
In the Azure Portal, navigate to your DocumentDB account, and then click Keys.
Copy the URI from the portal and paste it into <your endpoint URI>
in the program.cs file. Then copy the PRIMARY KEY from the portal and paste it into <your key>
.
Next, we'll start the application by creating a new instance of the DocumentClient.
Below the Main method, add this new asynchronous task called GetStartedDemo, which will instantiate our new DocumentClient.
static void Main(string[] args)
{
}
// ADD THIS PART TO YOUR CODE
private async Task GetStartedDemo()
{
this.client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
}
Add the following code to run your asynchronous task from your Main method. The Main method will catch exceptions and write them to the console.
static void Main(string[] args)
{
// ADD THIS PART TO YOUR CODE
try
{
Program p = new Program();
p.GetStartedDemo().Wait();
}
catch (DocumentClientException de)
{
Exception baseException = de.GetBaseException();
Console.WriteLine("{0} error occurred: {1}, Message: {2}", de.StatusCode, de.Message, baseException.Message);
}
catch (Exception e)
{
Exception baseException = e.GetBaseException();
Console.WriteLine("Error: {0}, Message: {1}", e.Message, baseException.Message);
}
finally
{
Console.WriteLine("End of demo, press any key to exit.");
Console.ReadKey();
}
Press F5 to run your application. The console window output displays the message End of demo, press any key to exit.
confirming that the connection was made. You can then close the console window.
Congratulations! You have successfully connected to a DocumentDB account, let's now take a look at working with DocumentDB resources.
Before you add the code for creating a database, add a helper method for writing to the console.
Copy and paste the WriteToConsoleAndPromptToContinue method after the GetStartedDemo method.
// ADD THIS PART TO YOUR CODE
private void WriteToConsoleAndPromptToContinue(string format, params object[] args)
{
Console.WriteLine(format, args);
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
Your DocumentDB database can be created by using the CreateDatabaseAsync method of the DocumentClient class. A database is the logical container of JSON document storage partitioned across collections.
Copy and paste the CreateDatabaseIfNotExists method after the WriteToConsoleAndPromptToContinue method.
// ADD THIS PART TO YOUR CODE
private async Task CreateDatabaseIfNotExists(string databaseName)
{
// Check to verify a database with the id=FamilyDB does not exist
try
{
await this.client.ReadDatabaseAsync(UriFactory.CreateDatabaseUri(databaseName));
this.WriteToConsoleAndPromptToContinue("Found {0}", databaseName);
}
catch (DocumentClientException de)
{
// If the database does not exist, create a new database
if (de.StatusCode == HttpStatusCode.NotFound)
{
await this.client.CreateDatabaseAsync(new Database { Id = databaseName });
this.WriteToConsoleAndPromptToContinue("Created {0}", databaseName);
}
else
{
throw;
}
}
}
Copy and paste the following code to your GetStartedDemo method after the client creation. This will create a database named FamilyDB.
private async Task GetStartedDemo()
{
this.client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
// ADD THIS PART TO YOUR CODE
await this.CreateDatabaseIfNotExists("FamilyDB_oa");
Press F5 to run your application.
Congratulations! You have successfully created a DocumentDB database.
Warning
CreateDocumentCollectionAsync will create a new collection with reserved throughput, which has pricing implications. For more details, please visit our pricing page.
A collection can be created by using the CreateDocumentCollectionAsync method of the DocumentClient class. A collection is a container of JSON documents and associated JavaScript application logic.
Copy and paste the CreateDocumentCollectionIfNotExists method after your CreateDatabaseIfNotExists method.
// ADD THIS PART TO YOUR CODE
private async Task CreateDocumentCollectionIfNotExists(string databaseName, string collectionName)
{
try
{
await this.client.ReadDocumentCollectionAsync(UriFactory.CreateDocumentCollectionUri(databaseName, collectionName));
this.WriteToConsoleAndPromptToContinue("Found {0}", collectionName);
}
catch (DocumentClientException de)
{
// If the document collection does not exist, create a new collection
if (de.StatusCode == HttpStatusCode.NotFound)
{
DocumentCollection collectionInfo = new DocumentCollection();
collectionInfo.Id = collectionName;
// Configure collections for maximum query flexibility including string range queries.
collectionInfo.IndexingPolicy = new IndexingPolicy(new RangeIndex(DataType.String) { Precision = -1 });
// Here we create a collection with 400 RU/s.
await this.client.CreateDocumentCollectionAsync(
UriFactory.CreateDatabaseUri(databaseName),
collectionInfo,
new RequestOptions { OfferThroughput = 400 });
this.WriteToConsoleAndPromptToContinue("Created {0}", collectionName);
}
else
{
throw;
}
}
}
Copy and paste the following code to your GetStartedDemo method after the database creation. This will create a document collection named FamilyCollection_oa.
this.client = new DocumentClient(new Uri(EndpointUri), PrimaryKey);
await this.CreateDatabaseIfNotExists("FamilyDB_oa");
// ADD THIS PART TO YOUR CODE
await this.CreateDocumentCollectionIfNotExists("FamilyDB_oa", "FamilyCollection_oa");
Press F5 to run your application.
Congratulations! You have successfully created a DocumentDB document collection.
A document can be created by using the CreateDocumentAsync method of the DocumentClient class. Documents are user defined (arbitrary) JSON content. We can now insert one or more documents. If you already have data you'd like to store in your database, you can use DocumentDB's Data Migration tool to import the data into a database.
First, we need to create a Family class that will represent objects stored within DocumentDB in this sample. We will also create Parent, Child, Pet, Address subclasses that are used within Family. Note that documents must have an Id property serialized as id in JSON. Create these classes by adding the following internal sub-classes after the GetStartedDemo method.
Copy and paste the Family, Parent, Child, Pet, and Address classes after the WriteToConsoleAndPromptToContinue method.
private void WriteToConsoleAndPromptToContinue(string format, params object[] args)
{
Console.WriteLine(format, args);
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
// ADD THIS PART TO YOUR CODE
public class Family
{
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
public string LastName { get; set; }
public Parent[] Parents { get; set; }
public Child[] Children { get; set; }
public Address Address { get; set; }
public bool IsRegistered { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
public class Parent
{
public string FamilyName { get; set; }
public string FirstName { get; set; }
}
public class Child
{
public string FamilyName { get; set; }
public string FirstName { get; set; }
public string Gender { get; set; }
public int Grade { get; set; }
public Pet[] Pets { get; set; }
}
public class Pet
{
public string GivenName { get; set; }
}
public class Address
{
public string State { get; set; }
public string County { get; set; }
public string City { get; set; }
}
Copy and paste the CreateFamilyDocumentIfNotExists method after your CreateDocumentCollectionIfNotExists method.
// ADD THIS PART TO YOUR CODE
private async Task CreateFamilyDocumentIfNotExists(string databaseName, string collectionName, Family family)
{
try
{
await this.client.ReadDocumentAsync(UriFactory.CreateDocumentUri(databaseName, collectionName, family.Id));
this.WriteToConsoleAndPromptToContinue("Found {0}", family.Id);
}
catch (DocumentClientException de)
{
if (de.StatusCode == HttpStatusCode.NotFound)
{
await this.client.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(databaseName, collectionName), family);
this.WriteToConsoleAndPromptToContinue("Created Family {0}", family.Id);
}
else
{
throw;
}
}
}
And insert two documents, one each for the Andersen Family and the Wakefield Family.
Copy and paste the following code to your GetStartedDemo method after the document collection creation.
await this.CreateDatabaseIfNotExists("FamilyDB_oa");
await this.CreateDocumentCollectionIfNotExists("FamilyDB_oa", "FamilyCollection_oa");
// ADD THIS PART TO YOUR CODE
Family andersenFamily = new Family
{
Id = "Andersen.1",
LastName = "Andersen",
Parents = new Parent[]
{
new Parent { FirstName = "Thomas" },
new Parent { FirstName = "Mary Kay" }
},
Children = new Child[]
{
new Child
{
FirstName = "Henriette Thaulow",
Gender = "female",
Grade = 5,
Pets = new Pet[]
{
new Pet { GivenName = "Fluffy" }
}
}
},
Address = new Address { State = "WA", County = "King", City = "Seattle" },
IsRegistered = true
};
await this.CreateFamilyDocumentIfNotExists("FamilyDB_oa", "FamilyCollection_oa", andersenFamily);
Family wakefieldFamily = new Family
{
Id = "Wakefield.7",
LastName = "Wakefield",
Parents = new Parent[]
{
new Parent { FamilyName = "Wakefield", FirstName = "Robin" },
new Parent { FamilyName = "Miller", FirstName = "Ben" }
},
Children = new Child[]
{
new Child
{
FamilyName = "Merriam",
FirstName = "Jesse",
Gender = "female",
Grade = 8,
Pets = new Pet[]
{
new Pet { GivenName = "Goofy" },
new Pet { GivenName = "Shadow" }
}
},
new Child
{
FamilyName = "Miller",
FirstName = "Lisa",
Gender = "female",
Grade = 1
}
},
Address = new Address { State = "NY", County = "Manhattan", City = "NY" },
IsRegistered = false
};
await this.CreateFamilyDocumentIfNotExists("FamilyDB_oa", "FamilyCollection_oa", wakefieldFamily);
Press F5 to run your application.
Congratulations! You have successfully created two DocumentDB documents.
DocumentDB supports rich queries against JSON documents stored in each collection. The following sample code shows various queries - using both DocumentDB SQL syntax as well as LINQ - that we can run against the documents we inserted in the previous step.
Copy and paste the ExecuteSimpleQuery method after your CreateFamilyDocumentIfNotExists method.
// ADD THIS PART TO YOUR CODE
private void ExecuteSimpleQuery(string databaseName, string collectionName)
{
// Set some common query options
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1 };
// Here we find the Andersen family via its LastName
IQueryable<Family> familyQuery = this.client.CreateDocumentQuery<Family>(
UriFactory.CreateDocumentCollectionUri(databaseName, collectionName), queryOptions)
.Where(f => f.LastName == "Andersen");
// The query is executed synchronously here, but can also be executed asynchronously via the IDocumentQuery<T> interface
Console.WriteLine("Running LINQ query...");
foreach (Family family in familyQuery)
{
Console.WriteLine("\tRead {0}", family);
}
// Now execute the same query via direct SQL
IQueryable<Family> familyQueryInSql = this.client.CreateDocumentQuery<Family>(
UriFactory.CreateDocumentCollectionUri(databaseName, collectionName),
"SELECT * FROM Family WHERE Family.LastName = 'Andersen'",
queryOptions);
Console.WriteLine("Running direct SQL query...");
foreach (Family family in familyQueryInSql)
{
Console.WriteLine("\tRead {0}", family);
}
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
Copy and paste the following code to your GetStartedDemo method after the second document creation.
await this.CreateFamilyDocumentIfNotExists("FamilyDB_oa", "FamilyCollection_oa", wakefieldFamily);
// ADD THIS PART TO YOUR CODE
this.ExecuteSimpleQuery("FamilyDB_oa", "FamilyCollection_oa");
Before running the application, on the Project menu, click Project name Properties..., and then click Build. Clear the Prefer 32-bit box, as partition routing information cannot be extracted from the query when running in a 32-bit process.
Press F5 to run your application.
Congratulations! You have successfully queried against a DocumentDB collection.
The following diagram illustrates how the DocumentDB SQL query syntax is called against the collection you created, and the same logic applies to the LINQ query as well.
The FROM keyword is optional in the query because DocumentDB queries are already scoped to a single collection. Therefore, "FROM Families f" can be swapped with "FROM root r", or any other variable name you choose. DocumentDB will infer that Families, root, or the variable name you chose, reference the current collection by default.
DocumentDB supports replacing JSON documents.
Copy and paste the ReplaceFamilyDocument method after your ExecuteSimpleQuery method.
// ADD THIS PART TO YOUR CODE
private async Task ReplaceFamilyDocument(string databaseName, string collectionName, string familyName, Family updatedFamily)
{
try
{
await this.client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(databaseName, collectionName, familyName), updatedFamily);
this.WriteToConsoleAndPromptToContinue("Replaced Family {0}", familyName);
}
catch (DocumentClientException de)
{
throw;
}
}
Copy and paste the following code to your GetStartedDemo method after the query execution, at the end of the method. After replacing the document, this will run the same query again to view the changed document.
await this.CreateFamilyDocumentIfNotExists("FamilyDB_oa", "FamilyCollection_oa", wakefieldFamily);
this.ExecuteSimpleQuery("FamilyDB_oa", "FamilyCollection_oa");
// ADD THIS PART TO YOUR CODE
// Update the Grade of the Andersen Family child
andersenFamily.Children[0].Grade = 6;
await this.ReplaceFamilyDocument("FamilyDB_oa", "FamilyCollection_oa", "Andersen.1", andersenFamily);
this.ExecuteSimpleQuery("FamilyDB_oa", "FamilyCollection_oa");
Press F5 to run your application.
Congratulations! You have successfully replaced a DocumentDB document.
DocumentDB supports deleting JSON documents.
Copy and paste the DeleteFamilyDocument method after your ReplaceFamilyDocument method.
// ADD THIS PART TO YOUR CODE
private async Task DeleteFamilyDocument(string databaseName, string collectionName, string documentName)
{
try
{
await this.client.DeleteDocumentAsync(UriFactory.CreateDocumentUri(databaseName, collectionName, documentName));
Console.WriteLine("Deleted Family {0}", documentName);
}
catch (DocumentClientException de)
{
throw;
}
}
Copy and paste the following code to your GetStartedDemo method after the second query execution, at the end of the method.
await this.ReplaceFamilyDocument("FamilyDB_oa", "FamilyCollection_oa", "Andersen.1", andersenFamily);
this.ExecuteSimpleQuery("FamilyDB_oa", "FamilyCollection_oa");
// ADD THIS PART TO CODE
await this.DeleteFamilyDocument("FamilyDB_oa", "FamilyCollection_oa", "Andersen.1");
Press F5 to run your application.
Congratulations! You have successfully deleted a DocumentDB document.
Deleting the created database will remove the database and all children resources (collections, documents, etc.).
Copy and paste the following code to your GetStartedDemo method after the document delete to delete the entire database and all children resources.
this.ExecuteSimpleQuery("FamilyDB_oa", "FamilyCollection_oa");
await this.DeleteFamilyDocument("FamilyDB_oa", "FamilyCollection_oa", "Andersen.1");
// ADD THIS PART TO CODE
// Clean up/delete the database
await this.client.DeleteDatabaseAsync(UriFactory.CreateDatabaseUri("FamilyDB_oa"));
Press F5 to run your application.
Congratulations! You have successfully deleted a DocumentDB database.
Hit F5 in Visual Studio to build the application in debug mode.
You should see the output of your get started app. The output will show the results of the queries we added and should match the example text below.
Created FamilyDB_oa
Press any key to continue ...
Created FamilyCollection_oa
Press any key to continue ...
Created Family Andersen.1
Press any key to continue ...
Created Family Wakefield.7
Press any key to continue ...
Running LINQ query...
Read {"id":"Andersen.1","LastName":"Andersen","District":"WA5","Parents":[{"FamilyName":null,"FirstName":"Thomas"},{"FamilyName":null,"FirstName":"Mary Kay"}],"Children":[{"FamilyName":null,"FirstName":"Henriette Thaulow","Gender":"female","Grade":5,"Pets":[{"GivenName":"Fluffy"}]}],"Address":{"State":"WA","County":"King","City":"Seattle"},"IsRegistered":true}
Running direct SQL query...
Read {"id":"Andersen.1","LastName":"Andersen","District":"WA5","Parents":[{"FamilyName":null,"FirstName":"Thomas"},{"FamilyName":null,"FirstName":"Mary Kay"}],"Children":[{"FamilyName":null,"FirstName":"Henriette Thaulow","Gender":"female","Grade":5,"Pets":[{"GivenName":"Fluffy"}]}],"Address":{"State":"WA","County":"King","City":"Seattle"},"IsRegistered":true}
Replaced Family Andersen.1
Press any key to continue ...
Running LINQ query...
Read {"id":"Andersen.1","LastName":"Andersen","District":"WA5","Parents":[{"FamilyName":null,"FirstName":"Thomas"},{"FamilyName":null,"FirstName":"Mary Kay"}],"Children":[{"FamilyName":null,"FirstName":"Henriette Thaulow","Gender":"female","Grade":6,"Pets":[{"GivenName":"Fluffy"}]}],"Address":{"State":"WA","County":"King","City":"Seattle"},"IsRegistered":true}
Running direct SQL query...
Read {"id":"Andersen.1","LastName":"Andersen","District":"WA5","Parents":[{"FamilyName":null,"FirstName":"Thomas"},{"FamilyName":null,"FirstName":"Mary Kay"}],"Children":[{"FamilyName":null,"FirstName":"Henriette Thaulow","Gender":"female","Grade":6,"Pets":[{"GivenName":"Fluffy"}]}],"Address":{"State":"WA","County":"King","City":"Seattle"},"IsRegistered":true}
Deleted Family Andersen.1
End of demo, press any key to exit.
Congratulations! You've completed this NoSQL tutorial and have a working C# console application!
If you didn't have time to complete the steps in this tutorial, or just want to download the code samples, you can get it from Github.
To build the GetStarted solution, you will need the following:
- An active Azure account. If you don't have one, you can sign up for a free account.
- A DocumentDB account.
- The GetStarted solution available on GitHub.
To restore the references to the DocumentDB .NET SDK in Visual Studio, right-click the GetStarted solution in Solution Explorer, and then click Enable NuGet Package Restore. Next, in the App.config file, update the EndpointUrl and AuthorizationKey values as described in Connect to a DocumentDB account.
Before running the application, on the Project menu, click Project name Properties..., and then click Build. Clear the Prefer 32-bit box.
That's it, build it and you're on your way!
- Want a more complex ASP.NET MVC NoSQL tutorial? See Build a web application with ASP.NET MVC using DocumentDB.
- Want to perform scale and performance testing with DocumentDB? See Performance and Scale Testing with Azure DocumentDB
- Learn how to monitor a DocumentDB account.
- Run queries against our sample dataset in the Query Playground.
- Learn more about the programming model in the Develop section of the DocumentDB documentation page.