I am working on a project that leverages both Azure Functions as well as Cosmos DB. In trying to get both of these components wired together, I found that there are very few examples that work with the most recent versions of these components. I also saw examples that could work at a small scale, but don’t show industry-standard best practices, and would lead to performance issues if deployed in an environment with any meaningful traffic.
To that end, I put together this blog post showing how to set up an Azure Functions project in .NET Core 2.2 to integrate with Cosmos DB’s SQL API using its native tooling.
In order to get this example solution running, make sure that you have the most recent version of Visual Studio, which as of writing this post, is Visual Studio 2019 16.2.4. Also, make sure that you have the Azure SDK installed along with .NET Core 2.2 SDK.
Also, be sure to download and install the Azure Cosmos DB Emulator. This is what allows a developer to run a simulated Cosmos DB instance on their machine.
Create New Azure Function Solution
The first step is to create a new Azure Function solution. Open Visual Studio, then go to File -> New -> Project.
Search for “Function”, make sure that “Azure Function” shows up, then click Next.
Name the new project
BagelBoss.API.API, and name the solution
BagelBoss.API. Then click on Create.
For the first trigger, select an Http trigger. Use the defaults for a Storage Emulator and Function access rights. Then click Create.
Once created, right-click on the
BagelBoss.API.API project, click on Properties. Then change the Target framework to .NET Core 2.2, if it is not already configured that way. Then save changes.
Next, open up the nuGet Package Manager for the solution. Search for “Microsoft.Azure.Cosmos”. Install the latest version, which at the time of writing this post is 3.1.1.
Also, search for and install “Microsoft.Azure.Functions.Extensions”. This will allow for dependency injection in the Function App.
Also make sure that all nuGet packages installed by default are updated to their latest versions.
Then create a new class in the project called
Startup. This class will be where the Dependency Injection is configured. It needs to extend from
Microsoft.Azure.Functions.Extensions.DependencyInjection.FunctionsStartup. There also needs to be a
FunctionsStartup attribute added with the fully qualified class name.
Next, add in the following lines to define the resolution of a Cosmos DB Container within the application. This is configured to be a singleton to make sure that the same connection is reused for invocations of the Function App. This reduces the amount of time it takes to process the Function, as it does not have to connect and dispose of the database connection each time it is invoked. Direct connection mode is also used to reduce the round trips on reads and writes.
I have also chosen in this example to create the database and container if they do not already exist. If the control of when databases and containers are created and how they’re configured needs to be managed outside of the application code, those lines can be omitted. I also chose to synchronously use them to simplify the provider method itself as it is synchronous by default.
Then, create a new folder in the project named
Entities, and add a new class called
Bagel. This class needs to have a property of
Id, though it should be written out in the lowercase
id for the Cosmos DB SQL API to properly understand it. It will also have a property for
Store, which will be used as the partition key. There will also be another property for
Schmear to describe what kind of spread needs to be inside the bagel if any. I also find it helpful to setup a getter for the
Now, go to the generated Http trigger, request an instance of the Container from the Dependency Injector. Also make sure to switch this over to a non-static class and method.
Then, inside of the trigger method, create an instance of a
Bagel, fill it with some
Schmear, save it to the container, then return a response to the caller.
Then, start the Azure Cosmos DB Emulator. Once started, it will pop up a new browser tab/window with configurations that will be needed in later steps. Specifically the URI and Primary Key.
In the Function App project, open up the
local.settings.json file. Add in the new properties that start with
CosmosDb as specified in this screenshot:
Run the Application
Now that the application has been coded and configured, start the application up. If everything was successful, a console should appear like this:
Follow the instructions on the bottom to execute a HTTP GET against the URL the function is listening for. Specify a name in the URL that will be used as the store’s name. Then observe the response.
To see the data saved to the Cosmos DB emulator, open its Data Explorer. Then go to Explorer, expand the
BagelBoss database, open the
Bagels container, click on Items. Note the items that show up on the right side.
Through the course of this blog post, I showed how to create a new Azure Function App, and have its data sourced from an Azure Cosmos DB Emulator.
These two technologies represent the best-in-brand PaaS offerings from Azure, so it is easy to see how developers could accelerate the delivery of functionality by moving toward a serverless programming model like Azure services provide.