Lab: Constructing a polyglot data solution

Student lab manual

Lab scenario

You have been assigned the task of updating your company’s existing retail web application to use more than one data service in Microsoft Azure. Your company’s goal is to leverage the best data service for each application component. After conducting thorough research, you decide to migrate your inventory database from Azure SQL Database to Azure Cosmos DB. You have also decided to implement your shopping cart functionality using Azure Cache for Redis. Since the existing application code is modular, you will take the existing application and add new providers for these data services hosted in Azure.

Objectives

After you complete this lab, you will be able to:

  • Create instances of various database services using the Azure Portal.

  • Write C# code to connect to Azure SQL Database.

  • Write C# code to connect to Azure Cosmos DB.

  • Write C# code to connect to Azure Cache for Redis.

Lab setup

  • Estimated Time: 90 minutes

Instructions

Before you start

Sign in to the lab virtual machine

Ensure that you are signed in to your Windows 10 virtual machine using the following credentials:

  • Username: Admin

  • Password: Pa55w.rd

Review installed applications

Observe the taskbar located at the bottom of your Windows 10 desktop. The taskbar contains the icons for the applications you will use in this lab:

  • Microsoft Edge

  • File Explorer

  • Visual Studio Code

Download the lab files

  1. On the taskbar, select the Windows PowerShell icon.

  2. In the PowerShell command prompt, change the current working directory to the Allfiles (F):\ path:

    cd F:
    
  3. Within the command prompt, enter the following command and press Enter to clone the microsoftlearning/AZ-203-DevelopingSolutionsforMicrosoftAzure project hosted on GitHub into the Allfiles (F):\ drive:

    git clone --depth 1 --no-checkout https://github.com/microsoftlearning/AZ-203-DevelopingSolutionsForMicrosoftAzure .
    
  4. Within the command prompt, enter the following command and press Enter to check out the lab files necessary to complete the AZ-203T03 lab:

    git checkout master -- Allfiles/*
    
  5. Close the currently running Windows PowerShell command prompt application.

Exercise 1: Creating database resources in Azure

Task 1: Open the Azure portal

  1. Sign in to the Azure portal (https://portal.azure.com).

  2. If this is your first time signing in to the Azure portal, you will see a dialog box offering a tour of the portal. Select the Get Started button to skip the tour.

Task 2: Create an Azure Cache for Redis resource

  1. Create a new Azure Cache for Redis resource with the following details:

    • DNS name: polyrediscache[your name in lowercase]

    • New resource group: PolyglotData

    • Location: East US

    • Pricing tier: Basic C0 (250MB Cache)

    Note: Wait for Azure to finish creating the Azure Cache for Redis instance before you move forward with the lab. You will receive a notification when the Redis cache is created.

  2. Navigate to the blade for your newly created Azure Cache for Redis resource.

  3. Open the Access keys pane.

  4. In the Access keys pane, record the value in the Primary connection string (StackExchange.Redis) field.

    Note: You will use this value later in this lab.

Task 3: Create an Azure SQL server resource

  1. Create a new SQL server resource with the following details:

    • Server Name: polysqlsrvr[your name in lowercase]

    • Existing resource group: PolyglotData

    • Server admin login: testuser

    • Password: TestPa$$w0rd

    • Location: East US

    • Allow Azure Services to access server: Yes

    Note: Wait for Azure to finish creating the SQL server instance before you move forward with the lab. You will receive a notification when the SQL server is created.

Task 4: Create an Azure Cosmos DB account resource

  1. Create a new Azure Cosmos DB instance with the following details:

    • Account Name: polycosmos[your name in lowercase]

    • Existing resource group: PolyglotData

    • API: Core (SQL)

    • Location: East US

    • Geo-Redundancy: Disable

    • Multi-region Writes: Disable

    Note: Wait for Azure to finish creating the Azure Cosmos DB account before you move forward with the lab. You will receive a notification when the Azure Cosmos DB account is created.

  2. Navigate to the blade for your newly created Azure Cosmos DB account resource.

  3. Open the Keys pane.

  4. In the Keys pane, record the value of the PRIMARY CONNECTION STRING field.

    Note: You will use these values later in this lab.

Task 5: Create an Azure Storage account resource

  1. Create a new Azure Storage account with the following details:

    • Storage account name: polystor[your name in lowercase]

    • Existing resource group: PolyglotData

    • Account kind: StorageV2 (general purpose v2)

    • Location: East US

    • Replication: Locally-redundant storage (LRS)

    • Performance: Standard

    • Access tier (default): Hot

    Note: Wait for Azure to finish creating the storage account before you move forward with the lab. You will receive a notification when the storage account is created.

Review

In this exercise, you created all the Azure resources that you will need for a polyglot data solution.

Exercise 2: Import databases and images

Task 1: Upload image blobs

  1. Navigate to the blade for the polystor* Azure Storage account you created earlier in this lab.

  2. Open the Containers pane.

  3. Create a new container with the following settings:

    • Name: images

    • Public access level: Blob (anonymous read access for blobs only)

  4. Navigate to the new images container.

  5. Open the Properties pane.

  6. In the Properties pane, record the value in the URL field.

    Note: You will use this value later in this lab.

  7. Return to the blade for the images container.

  8. Use the Upload button to upload the fourty-two .jpg image files located in the Allfiles (F):\Allfiles\Labs\03\Starter\Images folder on your lab machine.

    Note: It is recommended that you enable the Overwrite if files already exist option.

Task 2: Upload SQL .bacpac file

  1. Navigate back to the blade for the polystor* Azure Storage account.

  2. Open the Containers pane again.

  3. Create a new container with the following settings:

    • Name: databases

    • Public access level: Private (no anonymous access)

  4. Navigate to the new databases container.

  5. Use the Upload button to upload the AdventureWorks.bacpac file located in the Allfiles (F):\Allfiles\Labs\03\Starter\ folder on your lab machine.

    Note: It is recommended that you enable the Overwrite if files already exist option.

Task 3: Import SQL database

  1. Navigate to the blade for the polysqlsrvr* SQL server resource you created earlier in this lab.

  2. Import the database from your Azure Storage account into the SQL server instance using the following details:

    • Storage account: polystor*

    • Database backup blob: databases\AdventureWorks.bacpac

    • Database name: AdventureWorks

    • Server admin login: testuser

    • Password: TestPa$$w0rd

    Note: Wait for the database to be created before you continue with this lab.

Task 4: Use imported SQL Database

  1. Navigate back to the blade for the polysqlsrvr* SQL server resource.

  2. Open the Firewalls and virtual networks pane.

  3. Add your current (client) IP address to the list of allowed IP addresses and Save the list.

  4. Navigate to the blade for the AdventureWorks SQL database resource you recently imported.

  5. Open the Connection strings pane.

  6. Record the value of the ADO.NET (SQL Authentication) connection string.

  7. Update the connection string you recorded by replacing the placeholder values for {your_username} and {your_password} with the values testuser and TestPa$$w0rd, respectively.

    Note: For example, if your connection string was originally Server=tcp:polysqlsrvrinstructor.database.windows.net,1433;Initial Catalog=AdventureWorks;User ID={your_username};Password={your_password};, your updated connection string will be Server=tcp:polysqlsrvrinstructor.database.windows.net,1433;Initial Catalog=AdventureWorks;User ID=testuser;Password=TestPa$$w0rd;

  8. Navigate back to the blade for the AdventureWorks SQL database resource.

  9. Open the Query editor pane.

  10. Login using the following credentials:

    • Username: testuser

    • Password: TestPa$$w0rd

  11. Execute the following query and observe the results:

    SELECT * FROM AdventureWorks.dbo.Models
    

    Note: This query will return a list of models that will appear on the homepage of the web application.

  12. Execute this additional query and observe the results:

    SELECT * FROM AdventureWorks.dbo.Products
    

    Note: This query will return a list of products associated with each model.

Review

In this exercise, you imported all of the resources you will use with your web application.

Exercise 3: Open and configure a .NET Core web application

Task 1: Open and build the web application

  1. Using Visual Studio Code, open the solution folder found at: Allfiles (F):\Allfiles\Labs\03\Starter\AdventureWorks.

  2. Using a terminal, build the .NET Core solution:

    dotnet build
    

    Note: The dotnet build command will automatically restore any missing NuGet packages prior to building all projects in the folder.

  3. Dispose of the current terminal.

Task 2: Update SQL connection string

  1. Open the AdventureWorks.Web/appsettings.json file in Visual Studio Code.

  2. Replace the value of the ConnectionStrings.AdventureWorksSqlContext property with the ADO.NET (SQL Authentication) connection string of the SQL database that you recorded earlier in this lab.

    Note: It is important that you use your updated connection string here. The original connection string copied from the portal will not have the username and password necessary to connect to the SQL database.

  3. Save the appsettings.json file.

Task 3: Update blob base URL

  1. Replace the value of the Settings.BlobContainerUrl property with the URL property of the Azure Storage blob container named images that you recorded earlier in this lab.

  2. Save the appsettings.json file.

Task 4: Validate web application

  1. Using a terminal, change your context to the AdventureWorks.Web folder:

    cd .\AdventureWorks.Web\
    
  2. Using the same terminal, run the ASP.NET Core web application project:

    dotnet run
    

    Note: The dotnet run command will automatically build any changes to the project and then start the web application without a debugger attached. The command will output the URL of the running application and any assigned ports.

  3. Open the Microsoft Edge browser.

  4. In the open browser window, navigate to the web application hosted at localhost on port 5000.

    Note: The URL is http://localhost:5000.

  5. In the web application, observe the list of models displayed on the front page.

  6. Locate the Water Bottle model and select View Details.

  7. On the Water Bottle product detail page, select Add to Cart.

  8. Observe that the checkout functionality is currently disabled.

    Note: For now, only the product page functionality is implemented. You will implement the checkout logic later in this lab.

  9. Close the browser window showing your web application.

  10. Return to the Visual Studio Code window.

  11. Dispose of the current terminal.

Review

In this exercise, you configured your ASP.NET Core web application to connect to your resources in Azure.

Exercise 4: Migrating SQL data to Azure Cosmos DB

Task 1: Create migration project

  1. Using a terminal, create a new .NET project named AdventureWorks.Migrate in a folder with the same name:

    dotnet new console --name AdventureWorks.Migrate --langVersion 7.1
    

    Note: The dotnet new command will create a new console project in a folder with the same name as the project.

  2. Using the same terminal, add a reference to the existing AdventureWorks.Models project:

    dotnet add .\AdventureWorks.Migrate\AdventureWorks.Migrate.csproj reference .\AdventureWorks.Models\AdventureWorks.Models.csproj
    

    Note: The dotnet add reference command will add a reference to the model classes contained in the AdventureWorks.Models project.

  3. Using the same terminal, add a reference to the existing AdventureWorks.Context project:

    dotnet add .\AdventureWorks.Migrate\AdventureWorks.Migrate.csproj reference .\AdventureWorks.Context\AdventureWorks.Context.csproj
    

    Note: The dotnet add reference command will add a reference to the context classes contained in the AdventureWorks.Context project.

  4. Using the same terminal, change your context to the AdventureWorks.Migrate folder:

    cd .\AdventureWorks.Migrate\
    
  5. Using the same terminal, import version 2.2.6 of the Microsoft.EntityFrameworkCore.SqlServer from NuGet:

    dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 2.2.6
    

    Note: The dotnet add package command will add the Microsoft.EntityFrameworkCore.SqlServer package from NuGet.

  6. Using the same terminal, import version 3.7.0 of the Microsoft.Azure.Cosmos from NuGet:

    dotnet add package Microsoft.Azure.Cosmos --version 3.7.0
    

    Note: The dotnet add package command will add the Microsoft.Azure.Cosmos package from NuGet.

  7. Using the same terminal, build the .NET Core web application:

    dotnet build
    
  8. Dispose of the current terminal.

Task 2: Create .NET class

  1. Open the AdventureWorks.Migrate/Program.cs file in Visual Studio Code.

  2. Delete all existing code in the Program.cs file.

  3. Add the following using directives for libraries that will be referenced by the application:

    using AdventureWorks.Context;
    using AdventureWorks.Models;
    using Microsoft.Azure.Cosmos;
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
  4. Create a new Program class with two constant string properties and an asynchronous Main entry point method:

    public class Program
    {
        private const string sqlDBConnectionString = "";
        private const string cosmosDBConnectionString = "";
    
        public static async Task Main(string[] args)
        {
        }
    }
    
  5. Update the the sqlDBConnectionString string constant by setting its value to the ADO.NET (SQL Authentication) connection string of the SQL database that you recorded earlier in this lab.

    Note: It is important that you use your updated connection string here. The original connection string copied from the portal will not have the username and password necessary to connect to the SQL database.

  6. Update the the cosmosDBConnectionString string constant by setting its value to the PRIMARY CONNECTION STRING of the Azure Cosmos DB account that you recorded earier in this lab.

Task 3: Get SQL database records using Entity Framework

  1. Within the Main method, add the following blocks of code to implement an export of all Model and Product records from Azure SQL Database to local memory:

    await Console.Out.WriteLineAsync("Start Migration");
    
    AdventureWorksSqlContext context = new AdventureWorksSqlContext(sqlDBConnectionString);
    
    List<Model> items = await context.Models
        .Include(m => m.Products)
        .ToListAsync<Model>();
    
    await Console.Out.WriteLineAsync($"Total Azure SQL DB Records: {items.Count}");
    
  2. Save the Program.cs file.

  3. Using a terminal, change your context to the AdventureWorks.Migrate folder:

    cd .\AdventureWorks.Migrate\
    
  4. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    

    Note: If there are any build errors, please review the Program.cs file located in the Allfiles (F):\Allfiles\Labs\03\Solution\AdventureWorks\AdventureWorks.Migrate folder.

  5. Dispose of the current terminal.

Task 4: Insert items into Azure Cosmos DB

  1. Still within the Main method, add the following blocks of code to implement an import of the in-memory Model and Product data as documents to Azure Cosmos DB:

    CosmosClient client = new CosmosClient(cosmosDBConnectionString);
    
    Database database = await client.CreateDatabaseIfNotExistsAsync("Retail");
    
    Container container = await database.CreateContainerIfNotExistsAsync("Online",
        partitionKeyPath: $"/{nameof(Model.Category)}",
        throughput: 1000
    );
    
    int count = 0;
    foreach (var item in items)
    {
        ItemResponse<Model> document = await container.UpsertItemAsync<Model>(item);
        await Console.Out.WriteLineAsync($"Upserted document #{++count:000} [Activity Id: {document.ActivityId}]");
    }
    
    await Console.Out.WriteLineAsync($"Total Azure Cosmos DB Documents: {count}");
    
  2. Save the Program.cs file.

  3. Using a terminal, change your context to the AdventureWorks.Migrate folder:

    cd .\AdventureWorks.Migrate\
    
  4. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    

    Note: If there are any build errors, please review the Program.cs file located in the Allfiles (F):\Allfiles\Labs\03\Solution\AdventureWorks\AdventureWorks.Migrate folder.

Task 5: Perform migration

  1. Using the same terminal, run the ASP.NET Core web application project:

    dotnet run
    

    Note: The dotnet run command will start the console application.

  2. Observe the various data that is printed to the screen including; initial SQL record count, individual upsert activity identifiers, final Azure Cosmos DB document count.

  3. Dispose of the current terminal.

Task 6: Validate migration

  1. Return to the Microsoft Edge browser window showing the Azure portal.

  2. Navigate to the blade for the polycosmos* Azure Cosmos DB account you created earlier in this lab.

  3. Open the Data Explorer pane.

  4. Create a new SQL query tab within the context of the Retail database and Online container.

  5. Execute the following query and observe the results:

    SELECT * FROM models
    
  6. Execute the following query and observe the results:

    SELECT VALUE COUNT(1) FROM models
    

Review

In this exercise, you used Entity Framework and the .NET SDK for Azure Cosmos DB to migrate data from Azure SQL Database to Azure Cosmos DB.

Exercise 5: Accessing Azure Cosmos DB using .NET

Task 1: Update Library with the Cosmos SDK and references

  1. Using a terminal, change your context to the AdventureWorks.Context folder:

    cd .\AdventureWorks.Context\
    
  2. Using the same terminal, import the Microsoft.Azure.Cosmos from NuGet:

    dotnet add package Microsoft.Azure.Cosmos --version 3.0.0
    

    Note: The dotnet add package command will add the Microsoft.Azure.Cosmos package from NuGet.

  3. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    
  4. Dispose of the current terminal.

Task 2: Write .NET code to connect to Azure Cosmos DB

  1. Create a new AdventureWorks.Context/AdventureWorksCosmosContext.cs file in Visual Studio Code.

  2. Add the following using directives for libraries that will be referenced by the application:

    using AdventureWorks.Models;
    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
  3. Enter the following code to add a AdventureWorks.Context namespace block:

    namespace AdventureWorks.Context
    {
    }
    
  4. Create a new AdventureWorksCosmosContext class that implements the IAdventureWorksProductContext interface with a single readonly Container variable:

    public class AdventureWorksCosmosContext : IAdventureWorksProductContext
    {
        private readonly Container _container;
    }
    
  5. Within the AdventureWorksCosmosContext class, add a new constructor that creates a new instance of the CosmosClient class and then obtain both a Database and Container instance from the client:

    public AdventureWorksCosmosContext(string connectionString, string database = "Retail", string container = "Online")
    {
        _container = new CosmosClient(connectionString)
            .GetDatabase(database)
            .GetContainer(container);
    }
    
  6. Within the AdventureWorksCosmosContext class, add a new FindModelAsync method that creates a LINQ query, transforms it into an iterator, iterates over the result set, and then returns the single item in the result set:

    public async Task<Model> FindModelAsync(Guid id)
    {
        var iterator = _container.GetItemLinqQueryable<Model>()
            .Where(m => m.id == id)
            .ToFeedIterator<Model>();
    
        List<Model> matches = new List<Model>();
        while (iterator.HasMoreResults)
        {
            var next = await iterator.ReadNextAsync();
            matches.AddRange(next);
        }
    
        return matches.SingleOrDefault();
    }
    
  7. Within the AdventureWorksCosmosContext class, add a new GetModelsAsync method that executes a sql query, gets the query result iterator, iterates over the result set, and then returns the union of all results:

    public async Task<List<Model>> GetModelsAsync()
    {
        string query = $@"SELECT * FROM items";
    
        var iterator = _container.GetItemQueryIterator<Model>(query);
    
        List<Model> matches = new List<Model>();
        while (iterator.HasMoreResults)
        {
            var next = await iterator.ReadNextAsync();
            matches.AddRange(next);
        }
    
        return matches;
    }
    
  8. Within the AdventureWorksCosmosContext class, add a new FindProductAsync method that executes a sql query, gets the query result iterator, iterates over the result set, and then returns the single item in the result set:

    public async Task<Product> FindProductAsync(Guid id)
    {
        string query = $@"SELECT VALUE products
                            FROM models
                            JOIN products in models.Products
                            WHERE products.id = '{id}'";
    
        var iterator = _container.GetItemQueryIterator<Product>(query);
    
        List<Product> matches = new List<Product>();
        while (iterator.HasMoreResults)
        {
            var next = await iterator.ReadNextAsync();
            matches.AddRange(next);
        }
    
        return matches.SingleOrDefault();
    }
    
  9. Save the AdventureWorksCosmosContext.cs file.

  10. Using a terminal, change your context to the AdventureWorks.Context folder:

    cd .\AdventureWorks.Context\
    
  11. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    

    Note: If there are any build errors, please review the AdventureWorksCosmosContext.cs file located in the Allfiles (F):\Allfiles\Labs\03\Solution\AdventureWorks\AdventureWorks.Context folder.

  12. Dispose of the current terminal.

Task 3: Update Azure Cosmos DB connection string

  1. Open the AdventureWorks.Web/appsettings.json file in Visual Studio Code.

  2. Replace the value of the ConnectionStrings.AdventureWorksCosmosContext property with the PRIMARY CONNECTION STRING of the Azure Cosmos DB account that you recorded earier in this lab.

  3. Save the appsettings.json file.

Task 4: Update .NET application startup logic

  1. Open the AdventureWorks.Web/Startup.cs file in Visual Studio Code.

  2. In the Startup class, locate the existing ConfigureProductService method.

    Note: The current product service uses SQL as its database.

  3. Replace the ConfigureProductService method implementation with the following code:

    public void ConfigureProductService(IServiceCollection services)
    {
        services.AddScoped<IAdventureWorksProductContext, AdventureWorksCosmosContext>(provider =>
                new AdventureWorksCosmosContext(
                    _configuration.GetConnectionString(nameof(AdventureWorksCosmosContext))
                )
        );
    }
    
  4. Save the Startup.cs file.

Task 5: Validate .NET application successfully connects to Azure Cosmos DB

  1. Using a terminal, change your context to the AdventureWorks.Web folder:

    cd .\AdventureWorks.Web\
    
  2. Using the same terminal, run the ASP.NET Core web application project:

    dotnet run
    

    Note: The dotnet run command will automatically build any changes to the project and then start the web application without a debugger attached. The command will output the URL of the running application and any assigned ports.

  3. Open the Microsoft Edge browser.

  4. In the open browser window, navigate to the web application hosted at localhost on port 5000.

    Note: The URL is http://localhost:5000.

  5. In the web application, observe the list of models displayed on the front page.

  6. Locate the Touring-1000 model and select View Details.

  7. On the Touring-1000 product detail page, perform the following actions:

    1. In the Select options list, select Touring-1000 Yellow, 50, $2,384.07.

    2. Select Add to Cart.

  8. Observe that the checkout functionality is still disabled.

    Note: In the next exercise, you will implement the checkout logic.

  9. Close the browser window showing your web application.

  10. Return to the Visual Studio Code window.

  11. Dispose of the current terminal.

Review

In this exercise, you wrote C# code to query an Azure Cosmos DB collection using the .NET SDK.

Exercise 6: Accessing Azure Cache for Redis using .NET

Task 1: Update Library with the StackExchange.Redis SDK and references

  1. Using a terminal, change your context to the AdventureWorks.Context folder:

    cd .\AdventureWorks.Context\
    
  2. Using the same terminal, import the Newtonsoft.Json from NuGet:

    dotnet add package Newtonsoft.Json --version 12.0.2
    

    Note: The dotnet add package command will add the Newtonsoft.Json package from NuGet.

  3. Using the same terminal, import the StackExchange.Redis from NuGet:

    dotnet add package StackExchange.Redis --version 2.0.601
    

    Note: The dotnet add package command will add the StackExchange.Redis package from NuGet.

  4. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    
  5. Dispose of the current terminal.

Task 2: Write .NET code to connect to Azure Cache for Redis

  1. Create a new AdventureWorks.Context/AdventureWorksRedisContext.cs file in Visual Studio Code.

  2. Add the following using directives for libraries that will be referenced by the application:

    using AdventureWorks.Models;
    using Newtonsoft.Json;
    using StackExchange.Redis;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading.Tasks;
    
  3. Enter the following code to add a AdventureWorks.Context namespace block:

    namespace AdventureWorks.Context
    {
    }
    
  4. Create a new AdventureWorksRedisContext class that implements the IAdventureWorksCheckoutContext interface with a single readonly IDatabase variable:

    public class AdventureWorksRedisContext : IAdventureWorksCheckoutContext
    {
        private readonly IDatabase _database;
    }
    
  5. Within the AdventureWorksRedisContext class, add a new constructor that creates a new instance of the ConnectionMultiplexer class and then get the database instance:

    public AdventureWorksRedisContext(string connectionString)
    {
        ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(connectionString);
        _database = connection.GetDatabase();
    }
    
  6. Within the AdventureWorksRedisContext class, add a new AddProductToCartAsync method that gets the current value from a key, creates a new list if one does not already exists, adds the product to the list, and then stores the list as the new value for the key in the database:

    public async Task AddProductToCartAsync(string uniqueIdentifier, Product product)
    {
        RedisValue result = await _database.StringGetAsync(uniqueIdentifier);
        List<Product> products = new List<Product>();
        if (!result.IsNullOrEmpty)
        {
            List<Product> parsed = JsonConvert.DeserializeObject<List<Product>>(result.ToString());
            products.AddRange(parsed);
        }
        products.Add(product);
        string json = JsonConvert.SerializeObject(products);
        await _database.StringSetAsync(uniqueIdentifier, json);
    }
    
  7. Within the AdventureWorksRedisContext class, add a new GetProductsInCartAsync method that gets the list from the database and parse the JSON value into a collection of Product instances:

    public async Task<List<Product>> GetProductsInCartAsync(string uniqueIdentifier)
    {
        string json = await _database.StringGetAsync(uniqueIdentifier);
        List<Product> products = JsonConvert.DeserializeObject<List<Product>>(json ?? "[]");
        return products;
    }
    
  8. Within the AdventureWorksRedisContext class, add a new ClearCart method that removes a key and its associated values from the database:

    public async Task ClearCart(string uniqueIdentifier)
    {
        await _database.KeyDeleteAsync(uniqueIdentifier);
    }
    
  9. Save the AdventureWorksRedisContext.cs file.

  10. Using a terminal, change your context to the AdventureWorks.Context folder:

    cd .\AdventureWorks.Context\
    
  11. Using the same terminal, build the ASP.NET Core web application project:

    dotnet build
    

    Note: If there are any build errors, please review the AdventureWorksRedisContext.cs file located in the Allfiles (F):\Allfiles\Labs\03\Solution\AdventureWorks\AdventureWorks.Context folder.

  12. Dispose of the current terminal.

Task 3: Update Redis connection string

  1. Open the AdventureWorks.Web/appsettings.json file in Visual Studio Code.

  2. Replace the value of the ConnectionStrings.AdventureWorksRedisContext property with the Primary connection string (StackExchange.Redis) of the Azure Cache for Redis instance that you recorded earier in this lab.

  3. Replace the existing false value of the Settings.CartAvailable property with a new value of true.

  4. Save the appsettings.json file.

Task 4: Update .NET application startup logic

  1. Open the AdventureWorks.Web/Startup.cs file in Visual Studio Code.

  2. In the Startup class, locate the existing ConfigureCheckoutService method.

    Note: The current checkout service doesn’t use any database.

  3. Replace the ConfigureCheckoutService method implementation with the following code:

    public void ConfigureCheckoutService(IServiceCollection services)
    {
        services.AddScoped<IAdventureWorksCheckoutContext, AdventureWorksRedisContext>(provider =>
            new AdventureWorksRedisContext(
                _configuration.GetConnectionString(nameof(AdventureWorksRedisContext))
            )
        );
    }
    
  4. Save the Startup.cs file.

Task 5: Validate .NET application successfully connects to Azure Cache for Redis

  1. Using a terminal, change your context to the AdventureWorks.Web folder:

    cd .\AdventureWorks.Web\
    
  2. Using the same terminal, run the ASP.NET Core web application project:

    dotnet run
    

    Note: The dotnet run command will automatically build any changes to the project and then start the web application without a debugger attached. The command will output the URL of the running application and any assigned ports.

  3. Open the Microsoft Edge browser.

  4. In the open browser window, observe the list of models displayed on the front page.

  5. Locate the Mountain-400-W model and select View Details.

  6. On the Mountain-400-W product detail page, perform the following actions:

    1. In the Select options list, select Mountain-400-W Silver, 40, $769.49.

    2. Select Add to Cart.

  7. On the shopping cart page, observe the contents of the cart and then select Checkout.

  8. On the checkout page, observe the final receipt.

  9. Select the Shopping Cart icon at the top of the page.

  10. On the shopping cart page, observe the empty cart.

  11. Close the browser window showing your web application.

  12. Return to the Visual Studio Code window.

  13. Dispose of the current terminal.

Review

In this exercise, you used C# code to store and retrieve data from an Azure Cache for Redis store.

Exercise 7: Clean up subscription

Task 1: Open Azure Cloud Shell

  1. At the top of the Azure portal, click the Cloud Shell icon to open a new shell instance.

  2. If the Cloud Shell is not already configured, configure the shell for Bash by using the default settings.

  3. In the Cloud Shell command prompt at the bottom of the portal, type the following command and press Enter to list all resource groups in the subscription:

    az group list
    
  4. Type the following command and press Enter to view a list of possible commands to delete a resource group:

    az group delete --help
    

Task 2: Delete resource groups

  1. Type the following command and press Enter to delete the PolyglotData resource group:

    az group delete --name PolyglotData --no-wait --yes
    
  2. Close the Cloud Shell pane at the bottom of the portal.

Task 3: Close active applications

  1. Close the currently running Microsoft Edge application.

  2. Close the currently running Visual Studio Code application.

Review

In this exercise, you cleaned up your subscription by removing the resource groups used in this lab.