Connect to different regions with the Azure Cosmos DB for NoSQL SDK

When you enable geo-redundancy for an Azure Cosmos DB for NoSQL account, you can then use the SDK to read data from regions in any order you configure. This technique is beneficial when you distribute your read requests across all of your available read regions.

In this lab, you will configure the CosmosClient class to connect to read regions in a fallback order that you manually configure.

Prepare your development environment

If you have not already cloned the lab code repository for DP-420 to the environment where you’re working on this lab, follow these steps to do so. Otherwise, open the previously cloned folder in Visual Studio Code.

  1. Start Visual Studio Code.

    πŸ“ If you are not already familiar with the Visual Studio Code interface, review the Getting Started documentation

  2. Open the command palette and run Git: Clone to clone the https://github.com/microsoftlearning/dp-420-cosmos-db-dev GitHub repository in a local folder of your choice.

    πŸ’‘ You can use the CTRL+SHIFT+P keyboard shortcut to open the command palette.

  3. Once the repository has been cloned, open the local folder you selected in Visual Studio Code.

Create an Azure Cosmos DB for NoSQL account

Azure Cosmos DB is a cloud-based NoSQL database service that supports multiple APIs. When provisioning an Azure Cosmos DB account for the first time, you will select which of the APIs you want the account to support (for example, Mongo API or NoSQL API). Once the Azure Cosmos DB for NoSQL account is done provisioning, you can retrieve the endpoint and key and use them to connect to the Azure Cosmos DB for NoSQL account using the Azure SDK for .NET or any other SDK of your choice.

  1. In a new web browser window or tab, navigate to the Azure portal (portal.azure.com).

  2. Sign into the portal using the Microsoft credentials associated with your subscription.

  3. Select + Create a resource, search for Cosmos DB, and then create a new Azure Cosmos DB for NoSQL account resource with the following settings, leaving all remaining settings to their default values:

    Setting Value
    Subscription Your existing Azure subscription
    Resource group Select an existing or create a new resource group
    Account Name Enter a globally unique name
    Location Choose any available region
    Capacity mode Provisioned throughput
    Apply Free Tier Discount Do Not Apply

    πŸ“ Your lab environments may have restrictions preventing you from creating a new resource group. If that is the case, use the existing pre-created resource group.

  4. Wait for the deployment task to complete before continuing with this task.

  5. Go to the newly created Azure Cosmos DB account resource and navigate to the Replicate data globally pane.

  6. In the Replicate data globally pane, add two extra read regions to the account and then Save your changes.

  7. Wait for the replication task to complete before continuing with this task.

    πŸ“ This operation can take approximately 5-10 minutes.

  8. Record the names of the Write (primary) region and the two Read regions. You will use these region names later in this exercise.

    πŸ“ For example, if your primary region is North Europe, and your two read secondary regions are East US 2, and South Africa North; you will record all three of those names as-is.

  9. In the resource blade, navigate to the Data Explorer pane.

  10. In the Data Explorer pane, select New Container.

  11. In the New Container popup, enter the following values for each setting, and then select OK:

    Setting Value
    Database id Create new | cosmicworks
    Share throughput across containers Do not select
    Container id products
    Partition key /categoryId
    Container throughput Manual | 400
  12. Back in the Data Explorer pane, expand the cosmicworks database node and then observe the products container node within the hierarchy.

  13. In the Data Explorer pane, expand the cosmicworks database node, expand the products container node, and then select Items.

  14. Still in the Data Explorer pane, select New Item from the command bar. In the editor, replace the placeholder JSON item with the following content:

     {
       "id": "7d9273d9-5d91-404c-bb2d-126abb6e4833",
       "categoryId": "78d204a2-7d64-4f4a-ac29-9bfc437ae959",
       "categoryName": "Components, Pedals",
       "sku": "PD-R563",
       "name": "ML Road Pedal",
       "price": 62.09
     }
    
  15. Select Save from the command bar to add the JSON item:

  16. In the Items tab, observe the new item in the Items pane.

  17. In the resource blade, navigate to the Keys pane.

  18. This pane contains the connection details and credentials necessary to connect to the account from the SDK. Specifically:

    1. Notice the URI field. You will use this endpoint value later in this exercise.

    2. Notice the PRIMARY KEY field. You will use this key value later in this exercise.

  19. Return to Visual Studio Code.

Connect to the Azure Cosmos DB for NoSQL account from the SDK

Using the credentials from the newly created account, you will connect with the SDK classes and access the database and container instance from a different region.

  1. In the Explorer pane, browse to the 20-sdk-regions folder.

  2. Open the context menu for the 20-sdk-regions folder and then select Open in Integrated Terminal to open a new terminal instance.

    πŸ“ This command will open the terminal with the starting directory already set to the 20-sdk-regions folder.

  3. Build the project using the dotnet build command:

     dotnet build
    

    πŸ“ You may see a compiler warning that the endpoint and key variables are current unused. You can safely ignore this warning as you will use these variable in this task.

  4. Close the integrated terminal.

  5. Open the script.cs code file within the 20-sdk-regions folder.

    πŸ“ The [Microsoft.Azure.Cosmos][nuget.org/packages/microsoft.azure.cosmos/3.22.1] library has already been pre-imported from NuGet.

  6. Locate the string variable named endpoint. Set its value to the endpoint of the Azure Cosmos DB account you created earlier.

     string endpoint = "<cosmos-endpoint>";
    

    πŸ“ For example, if your endpoint is: httpsΒ­://dp420.documents.azure.com:443/, then the C# statement would be: string endpoint = β€œhttpsΒ­://dp420.documents.azure.com:443/”;.

  7. Locate the string variable named key. Set its value to the key of the Azure Cosmos DB account you created earlier.

     string key = "<cosmos-key>";
    

    πŸ“ For example, if your key is: fDR2ci9QgkdkvERTQ==, then the C# statement would be: string key = β€œfDR2ci9QgkdkvERTQ==”;.

  8. Save the script.cs code file.

Configure the .NET SDK with a preferred region list

The CosmosClientOptions class includes a property to configure the list of regions you would like to connect to with the SDK. The list is ordered by failover priority, attempting to connect to each region in the order that you configure.

  1. Create a new variable of generic type List<string> that contains a list of the regions you configured with your account, starting with the third region and ending with the first (primary) region. For example, if you created your Azure Cosmos DB for NoSQL account in the West US region, and then added South Africa North, and finally added East Asia; then your list variable would contain:

     List<string> regions = new()
     {
         "East Asia",
         "South Africa North",
         "West US"
     };
    

    πŸ’‘ Alternatively; you can use the Microsoft.Azure.Cosmos.Regions static class which includes built-in string properties for various Azure regions.

  2. Create a new instance of the CosmosClientOptions named options class with the ApplicationPreferredRegions property set to the regions variable:

     CosmosClientOptions options = new () 
     { 
         ApplicationPreferredRegions = regions
     };
    
  3. Create a new instance of the CosmosClient class named client passing in the endpoint, key, and options variables as constructor parameters:

     using CosmosClient client = new (endpoint, key, options); 
    
  4. Use the GetContainer method of the client variable to retrieve the existing container using the name of the database (cosmicworks) and the name of the container (products):

     Container container = client.GetContainer("cosmicworks", "products");
    
  5. Use the ReadItemAsync method of the container variable to retrieve the a specific item from the server and store the result in a variable named response of the nullable ItemResponse type:

     ItemResponse<dynamic> response = await container.ReadItemAsync<dynamic>(
         "7d9273d9-5d91-404c-bb2d-126abb6e4833",
         new PartitionKey("78d204a2-7d64-4f4a-ac29-9bfc437ae959")
     );
    
  6. Invoke the static Console.WriteLine method to print the current item identifier and the JSON diagnostic data:

     Console.WriteLine($"Item Id:\t{response.Resource.Id}");
     Console.WriteLine($"Response Diagnostics JSON");
     Console.WriteLine($"{response.Diagnostics}");
    
  7. Once you are done, your code file should now include:

     using Microsoft.Azure.Cosmos;
    
     string endpoint = "<cosmos-endpoint>";
     string key = "<cosmos-key>";
    
     List<string> regions = new()
     {
         "<read-region-2>",
         "<read-region-1>",
         "<write-region>"
     };
        
     CosmosClientOptions options = new () 
     { 
         ApplicationPreferredRegions = regions
     };
        
     using CosmosClient client = new(endpoint, key, options);
        
     Container container = client.GetContainer("cosmicworks", "products");
        
     ItemResponse<dynamic> response = await container.ReadItemAsync<dynamic>(
         "7d9273d9-5d91-404c-bb2d-126abb6e4833",
         new PartitionKey("78d204a2-7d64-4f4a-ac29-9bfc437ae959")
     );
        
     Console.WriteLine($"Item Id:\t{response.Resource.Id}");
     Console.WriteLine("Response Diagnostics JSON");
     Console.WriteLine($"{response.Diagnostics}");
    
  8. Save the script.cs code file.

  9. In Visual Studio Code, open the context menu for the 20-sdk-regions folder and then select Open in Integrated Terminal to open a new terminal instance.

  10. Build and run the project using the dotnet run command:

     dotnet run
    
  11. Observe the output from the terminal. The name of the container and the JSON diagnostic data should print to the console output.

  12. Review the JSON diagnostic data. Search for a property named HttpResponseStats and a child property named RequestUri. The value of this property should be a URI that includes the name and region you configured earlier in this lab.

    πŸ“ For example, if your account name is: dp420 and the first region you configured is East Asia; then the value of the JSON property would be: dp420-eastasia.documents.azure.com/dbs/cosmicworks/colls/products.

  13. Close the integrated terminal.

  14. Close Visual Studio Code.