Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This guide demonstrates how to build a .NET console application to connect to an Azure Cosmos DB for MongoDB vCore cluster. You set up your development environment, use the Azure.Identity
library from the Azure SDK for .NET to authenticate, and interact with the database to create, query, and update documents.
Prerequisites
- An existing Azure Cosmos DB for MongoDB (vCore) cluster.
The latest version of the Azure CLI in Azure Cloud Shell.
- If you prefer to run CLI reference commands locally, sign in to the Azure CLI by using the
az login
command.
- If you prefer to run CLI reference commands locally, sign in to the Azure CLI by using the
Microsoft Entra authentication configured for the cluster with your identity granted
dbOwner
role.- To enable Microsoft Entra authentication, review the configuration guide.
Latest version of .NET.
Retrieve Microsoft Entra tenant metadata
To retrieve an access token using the TokenCredential
class in Azure.Identity
, you need the unique identifier for the Microsoft Entra tenant. In this prerequisite step, use the Azure CLI to retrieve and record the tenantId
value.
Get the details for the currently logged-in Azure subscription using
az account show
.az account show
The command outputs a JSON response containing various fields.
{ "environmentName": "AzureCloud", "homeTenantId": "eeeeffff-4444-aaaa-5555-bbbb6666cccc", "id": "dddd3d3d-ee4e-ff5f-aa6a-bbbbbb7b7b7b", "isDefault": true, "managedByTenants": [], "name": "example-azure-subscription", "state": "Enabled", "tenantId": "eeeeffff-4444-aaaa-5555-bbbb6666cccc", "user": { "cloudShellID": true, "name": "kai@adventure-works.com", "type": "user" } }
Record the value of the
tenantId
property. This property is the unique identifier for your Microsoft Entra tenant and is sometimes referred to as the tenant ID. You use this value in steps within a subsequent section.
Configure your console application
Next, create a new console application project and import the necessary libraries to authenticate to your cluster.
In an empty directory, create a new .NET console application.
dotnet new console
Import the
Azure.Identity
package from NuGet.dotnet add package Azure.Identity
Next, import the
MongoDB.Driver
package.dotnet add package MongoDB.Driver
Build the .NET project
dotnet build
Connect to the cluster
Now, use the Azure.Identity
library to get a TokenCredential
to use to connect to your cluster. The official MongoDB driver has a special interface that must be implemented to obtain tokens from Microsoft Entra for use when connecting to the cluster.
In the Program.cs file, add using blocks for these
Azure.Identity
andMongoDB.Driver
namespaces.using Azure.Identity; using MongoDB.Driver;
Create a new class in a separate file that implements all required members of the
MongoDB.Driver.Authentication.Oidc.IOidcCallback
interface.using Azure.Core; using MongoDB.Driver.Authentication.Oidc; internal sealed class AzureIdentityTokenHandler( TokenCredential credential, string tenantId ) : IOidcCallback { private readonly string[] scopes = ["https://ossrdbms-aad.database.windows.net/.default"]; public OidcAccessToken GetOidcAccessToken(OidcCallbackParameters parameters, CancellationToken cancellationToken) { AccessToken token = credential.GetToken( new TokenRequestContext(scopes, tenantId: tenantId), cancellationToken ); return new OidcAccessToken(token.Token, token.ExpiresOn - DateTimeOffset.UtcNow); } public async Task<OidcAccessToken> GetOidcAccessTokenAsync(OidcCallbackParameters parameters, CancellationToken cancellationToken) { AccessToken token = await credential.GetTokenAsync( new TokenRequestContext(scopes, parentRequestId: null, tenantId: tenantId), cancellationToken ); return new OidcAccessToken(token.Token, token.ExpiresOn - DateTimeOffset.UtcNow); } }
Tip
For illustrative purposes, this class is named
AzureIdentityTokenHandler
. You can name this class anything you'd like. The rest of this guide assumes the class is namedAzureIdentityTokenHandler
.Go back to the editor for the Program.cs file.
Create a string variable with the name of your existing cluster. Then, use that variable to create a new instance of type
MongoUrl
usingMongoUrl.Create
string clusterName = "<azure-cosmos-db-mongodb-vcore-cluster-name>"; MongoUrl url = MongoUrl.Create($"mongodb+srv://{clusterName}.global.mongocluster.cosmos.azure.com/");
Configure a new
MongoSettings
instance using theMongoUrl
created in the previous steps and the standard best practice configuration for Azure Cosmos DB for MongoDB vCore.MongoClientSettings settings = MongoClientSettings.FromUrl(url); settings.UseTls = true; settings.RetryWrites = false; settings.MaxConnectionIdleTime = TimeSpan.FromMinutes(2);
Create a new credential of type
DefaultAzureCredential
.DefaultAzureCredential credential = new();
Tip
You can use any credential of type
TokenCredential
here.DefaultAzureCredential
is the most frictionless option for early development scenarios.Create a new instance of your class that implements
IOidcCallback
and configure it with the tenant ID you recorded earlier in this guide.string tenantId = "<microsoft-entra-tenant-id>"; AzureIdentityTokenHandler tokenHandler = new(credential, tenantId);
Configure the credential for your settings using
MongoCredential.CreateOidcCredential
and passing in your custom handler callback implementation.settings.Credential = MongoCredential.CreateOidcCredential(tokenHandler);
Freeze the settings and then create a new instance of
MongoClient
.settings.Freeze(); MongoClient client = new(settings); Console.WriteLine("Client created");
Perform common operations
Finally, use the official library to perform common tasks with databases, collections, and documents. Here, you use the same classes and methods you would use to interact with MongoDB or DocumentDB to manage your collections and items.
Represent your documents by creating a custom record type in its own file.
public record Product( string id, string category, string name, int quantity, decimal price, bool clearance );
Tip
For illustrative purposes, this struct is named
Product
. The rest of this guide assumes you have this struct already defined.Return back to the Program.cs file.
Get a pointer to your database using
MongoClient.GetDatabase
.string databaseName = "<database-name>"; IMongoDatabase database = client.GetDatabase(databaseName); Console.WriteLine("Database pointer created");
Then, use the database pointer to get a pointer to your collection using
IMongoDatabase.GetCollection<>
.string collectionName = "<collection-name>"; IMongoCollection<Product> collection = database.GetCollection<Product>(collectionName); Console.WriteLine("Collection pointer created");
Create and upsert two documents using the
IMongoCollection<>.ReplaceOneAsync
method.Product classicSurfboard = new( id: "bbbbbbbb-1111-2222-3333-cccccccccccc", category: "gear-surf-surfboards", name: "Kiama Classic Surfboard", quantity: 25, price: 790.00m, clearance: false ); Product paddleKayak = new( id: "cccccccc-2222-3333-4444-dddddddddddd", category: "gear-paddle-kayaks", name: "Lastovichka Paddle Kayak", quantity: 10, price: 599.99m, clearance: true ); await collection.ReplaceOneAsync<Product>( doc => doc.id == classicSurfboard.id, classicSurfboard, new ReplaceOptions { IsUpsert = true } ); Console.WriteLine($"Upserted document:\t{classicSurfboard.id}"); await collection.ReplaceOneAsync<Product>( doc => doc.id == paddleKayak.id, paddleKayak, new ReplaceOptions { IsUpsert = true } ); Console.WriteLine($"Upserted document:\t{paddleKayak.id}");
Read a single document from the collection using
IMongoCollection<>.Find
andIFindFluent<,>.SingleAsync
. Use a filter to specify the specific document you would like to find.Product document = await collection.Find( doc => doc.id == "cccccccc-2222-3333-4444-dddddddddddd" ).SingleAsync(); Console.WriteLine($"Found document:\t{document.name}");
Query for all documents that match a filter using the same
Find
method. Use a filter to define a specific property (likecategory
) and a specific value (likegear-surf-surfboards
). Enumerate the results usingIFindFluent<,>.ToListAsync
.List<Product> documents = await collection.Find( doc => doc.category == "gear-surf-surfboards" ).ToListAsync(); foreach (Product doc in documents) { Console.WriteLine($"Queried document:\t{doc}"); }
Delete a specific document from the collection using
IMongoCollection<>.DeleteOneAsync
and a filter.await collection.DeleteOneAsync( doc => doc.id == "bbbbbbbb-1111-2222-3333-cccccccccccc" ); Console.WriteLine($"Deleted document");
Save all of the code files in the project.
Run the project using
dotnet run
dotnet run
Observe the output from the running application.
Client created Database pointer created Collection pointer created Upserted document: bbbbbbbb-1111-2222-3333-cccccccccccc Upserted document: cccccccc-2222-3333-4444-dddddddddddd Found document: Lastovichka Paddle Kayak Queried document: Product { id = bbbbbbbb-1111-2222-3333-cccccccccccc, category = gear-surf-surfboards, name = Kiama Classic Surfboard, quantity = 25, price = 790.00, clearance = False } Deleted document