Exercice - Utiliser des services de base de données pour conserver des données à partir d’un projet .NET Aspire

Effectué

Dans cet exercice, vous remplacez les magasins de données actuels pour l’application cloud native en développement de votre entreprise. Actuellement, l’application utilise une base de données SQLite stockée localement pour les données de catalogue et un cache Redis en mémoire pour les paniers d’achat du client. Vous remplacez les magasins de données existants par PostgreSQL et MongoDB.

Prérequis à installer

Les prérequis pour .NET Aspire sont les suivants :

  • .NET 8
  • Préversion de Visual Studio 2022
  • Docker Desktop ou Podman
  • Charge de travail .NET Aspire dans Visual Studio

Si vous avez déjà installé les prérequis, vous pouvez passer à l’avance au clonage de l’application existante.

Installez .NET 8

Suivez ce lien .NET 8 et sélectionnez le programme d’installation approprié pour votre système d’exploitation. Par exemple, si vous utilisez Windows 11 et un processeur moderne, sélectionnez le kit de développement logiciel (SDK) .NET 8 x64 pour Windows.

Une fois le téléchargement terminé, exécutez le programme d’installation et suivez les instructions. Dans une fenêtre de terminal, exécutez la commande suivante pour vérifier que l’installation a réussi :

dotnet --version

Vous devez voir le numéro de version du kit de développement logiciel (SDK) .NET que vous avez installé. Par exemple :

8.0.300-preview.24203.14

Installer la préversion de Visual Studio 2022

Suivez ce lien de préversion de Visual Studio 2022, puis sélectionnez Télécharger la préversion. Une fois le téléchargement terminé, exécutez le programme d’installation et suivez les instructions.

Installer Docker Desktop

Suivez ce lien Docker Desktop, puis sélectionnez le programme d’installation approprié pour votre système d’exploitation. Une fois le téléchargement terminé, exécutez le programme d’installation et suivez les instructions.

Ouvrez l’application Docker Desktop et acceptez le contrat de service.

Installer la charge de travail .NET Aspire dans Visual Studio

Installez la charge de travail .NET Aspire à l’aide de l’interface CLI .NET :

  1. Ouvrez un terminal.

  2. Installez les charges de travail .NET Aspire avec les commandes suivantes :

    dotnet workload update
    dotnet workload install aspire
    dotnet workload list
    

    Vous devez voir les détails de la charge de travail .NET Aspire.

     Installed Workload Id      Manifest Version      Installation Source
    ---------------------------------------------------------------------------------------------
    aspire                     8.0.0/8.0.100         SDK 8.0.300-preview.24203, VS 17.10.34902.84
    
    Use `dotnet workload search` to find additional workloads to install.
    

Cloner et modifier l’application Northern Mountains

Utilisons git pour obtenir l’application Northern Mountains actuelle :

  1. Dans la ligne de commande, accédez à un dossier de votre choix dans lequel vous pouvez utiliser du code.

  2. Exécutez la commande suivante pour cloner l’exemple d’application Northern Mountains eShop :

    git clone -b aspire-databases https://github.com/MicrosoftDocs/mslearn-aspire-starter
    
  3. Démarrez Visual Studio, puis sélectionnez Ouvrir un projet ou une solution.

  4. Accédez au dossier où vous avez cloné eShop, ouvrez le dossier start, sélectionnez le fichier eShop.databases.sln, puis sélectionnez Ouvrir.

  5. Dans l’Explorateur de solutions, développez le projet eShop.AppHost, puis ouvrez le fichier Program.cs.

    // Databases
    
    var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
    
    // Identity Providers
    
    var idp = builder.AddKeycloakContainer("idp", tag: "23.0")
        .ImportRealms("../Keycloak/data/import");
    
    // DB Manager Apps
    
    builder.AddProject<Projects.Catalog_Data_Manager>("catalog-db-mgr");
    
    // API Apps
    
    var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api");
    
    var basketApi = builder.AddProject<Projects.Basket_API>("basket-api")
            .WithReference(basketStore)
            .WithReference(idp);
    
    // Apps
    
    // Force HTTPS profile for web app (required for OIDC operations)
    var webApp = builder.AddProject<Projects.WebApp>("webapp")
        .WithReference(catalogApi)
        .WithReference(basketApi)
        .WithReference(idp, env: "Identity__ClientSecret");
    

    Le code précédent montre la configuration actuelle de l’application. L’application utilise un cache Redis pour le magasin de paniers.

  6. Explorez le reste de l’application, concentrez-vous sur les projets Catalog.Data.Manager et Catalog.API et découvrez comment ils utilisent une base de données SQLite stockée localement.

  7. Pour démarrer l’application, appuyez sur F5, ou sélectionnez Débogage>Démarrer le débogage.

  8. Si la boîte de dialogue Démarrer Docker Desktop s’affiche, sélectionnez Oui.

  9. Quand le tableau de bord .NET Aspire d’eShop s’affiche, sélectionnez l’un des points de terminaison pour la ressource webapp :

    Capture d’écran du tableau de bord .NET Aspire d’eShop. Le point de terminaison webapp est mis en surbrillance.

  10. L’application s’ouvre dans un navigateur. Vous pouvez explorer l’application et voir comment elle fonctionne.

    Capture d’écran de la page d’accueil de l’eShop.

    Les informations d’identification d’utilisateur test sont test@example.com et P@$$w0rd1.

  11. Pour arrêter le débogage, appuyez sur Maj+F5, ou sélectionnez Déboguer> Arrêter le débogage.

Ajouter un composant PostgreSQL .NET Aspire

L’équipe responsable des microservices de catalogue a créé l’application pour utiliser une base de données SQLite stockée localement. Cette approche est adaptée au développement, mais l’équipe souhaite utiliser une base de données plus robuste pour la production.

Deux projets se connectent à la base de données SQLite, les projets Catalog.Data.Manager et Catalog.API. Le gestionnaire de données est utilisé uniquement pour alimenter la base de données en données. Vous devez donc vous concentrer sur le projet Catalog.API.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet Catalog.API, sélectionnez Ajouter>package .NET Aspire.

  2. Dans la zone de Recherche , ajoutez Npgsql.EntityFramework à la fin, puis appuyez sur Entrée.

  3. Sur la gauche, dans les résultats, sélectionnez Aspire.Npgsql.EntityFrameworkCore.PostgreSQL.

  4. Sur la droite, sélectionnez la liste déroulante de version, puis sélectionnez la dernière version 8.0.0.

  5. Sélectionnez Installer.

  6. Si la boîte de dialogue Aperçu des modifications s’affiche, sélectionnez Appliquer.

  7. Dans la boîte de dialogue Acceptation de la licence, sélectionnez J’accepte.

  8. Dans l’Explorateur de solutions, sélectionnez le projet Catalog.API pour afficher le contenu du fichier Catalog.API.csproj.

  9. Supprimez le PackageReference pour Microsoft.EntityFrameworkCore.Sqlite :

    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
    

Inscrire le nouveau DbContext PostgreSQL

  1. Dans l’Explorateur de solutions, développez le projet Catalog.API, puis ouvrez le fichier Program.cs.

  2. Remplacez SQLite DbContext :

    builder.Services.AddDbContext<CatalogDbContext>(
         options => options.UseSqlite(builder.Configuration.GetConnectionString("sqlconnection")
     	    ?? throw new InvalidOperationException(
     		    "Connection string 'sqlconnection' not found.")));
    

    Avec le nouveau DbContext PostgreSQL :

    builder.AddNpgsqlDbContext<CatalogDbContext>("CatalogDB");
    

    L’application n’a plus besoin de lire le fichier Database.db, alors supprimez les chaînes associées dans appsettings.json.

  3. Dans l’Explorateur de solutions, sous Catalog.API, sélectionnez appsettings.json.

  4. Supprimez les entrées ConnectionStrings, le fichier ressemble maintenant à ceci :

    {
      "Logging": {
        "LogLevel": {
          "Default": "Information",
          "Microsoft.AspNetCore": "Warning"
        }
      },
      "OpenApi": {
        "Endpoint": {
          "Name": "Catalog.API v1"
        },
        "Document": {
          "Description": "The Catalog Microservice HTTP API. This is a Data-Driven/CRUD microservice sample",
          "Title": "eShop - Catalog HTTP API",
          "Version": "v1"
        }
      },
      "CatalogOptions": {
        "PicBasePathFormat": "items/{0}/pic/"
      }
    }
    
    
  5. Cliquez avec le bouton droit sur le projet Catalog.Data.Manager, puis sélectionnez Supprimer.

  6. Dans la boîte de dialogue, cliquez sur OK.

L’équipe de base de données crée une sauvegarde de base de données PostgreSQL que vous pouvez utiliser pour créer et alimenter la base de données du catalogue. Vous pouvez afficher la sauvegarde dans le dossier Catalog.API/Seed.

Alimenter la base de données PostgreSQL à l’aide d’un volume lié

Le projet AppHost peut créer un conteneur de base de données PostgreSQL, l’alimenter avec des données à partir d’un volume lié, puis via des injection de dépendances transmettez des références au Catalog.API.

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet eShop.AppHost, sélectionnez Ajouter>package .NET Aspire.

  2. Dans la zone de Recherche, ajoutez PostgreSQL à la fin, puis appuyez sur Entrée.

  3. Sur la gauche, dans les résultats, sélectionnez Aspire.Hosting.PostgreSQL.

  4. Sur la droite, sélectionnez la liste déroulante de version, puis sélectionnez la dernière version 8.0.0.

  5. Sélectionnez Installer.

  6. Si la boîte de dialogue Aperçu des modifications s’affiche, sélectionnez Appliquer.

  7. Dans la boîte de dialogue Acceptation de la licence, sélectionnez J’accepte.

  8. Dans l’Explorateur de solutions, développez le projet eShop.AppHost, puis ouvrez le fichier Program.cs.

  9. Sous le commentaire //Databases, ajoutez le code suivant :

    // Databases
    
    var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
    var postgres = builder.AddPostgres("postgres")
        .WithEnvironment("POSTGRES_DB", "CatalogDB")
        .WithBindMount("../Catalog.API/Seed", "/docker-entrypoint-initdb.d").WithPgAdmin();
    var catalogDB = postgres.AddDatabase("CatalogDB");
    

    Le code précédent crée un conteneur de base de données PostgreSQL, ajoute une base de données nommée CatalogDB et lie le répertoire /docker-entrypoint-initdb.d au répertoire ../Catalog.API/Seed. Le code crée également un conteneur pour l’outil pgAdmin qui vous permet de gérer la base de données PostgreSQL.

  10. Transmettez la référence catalogDB au projet Catalog.API en ajoutant .WithReference(catalogDB), le code est maintenant :

    // API Apps
    
    var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api")
      .WithReference(catalogDB); 
    
  11. Le projet Catalog.Data.Manager n’est plus nécessaire. Supprimez donc le projet de AppHost. Supprimer ce code :

    // DB Manager Apps
    
    builder.AddProject<Projects.Catalog_Data_Manager>("catalog-db-mgr");
    

Tester l'application

L’utilisation de .NET Aspire a permis à votre équipe de supprimer un projet entier. En outre, l’API de catalogue a uniquement besoin d’une seule ligne de code pour ajouter le contexte de base de données PostgresSQL. L’injection de dépendances et la découverte de service à partir d’AppHost signifient qu’aucune autre modification du code n’est nécessaire pour permettre à l’API de se connecter à la nouvelle base de données.

  1. Compilez et démarrer l’application, appuyez sur F5, ou sélectionnez Débogage>Démarrer le débogage.

    Capture d’écran montrant le tableau de bord .NET Aspire mis à jour, avec les deux nouveaux conteneurs PostgreSQL mis en surbrillance.

    Il existe deux nouveaux conteneurs dans le tableau de bord qui hébergent le serveur de base de données PostgreSQL et l’outil pgAdmin. Il existe également une ressource de base de données PostgreSQL qui héberge la base de données CatalogDB.

  2. Utilisez pgAdmin pour vous connecter à la base de données PostgreSQL et explorer les données. Sélectionnez le point de terminaison postgres pgadmin.

    Capture d’écran de l’interface pgAdmin, mettant en évidence la navigation vers la table Catalogue.

  3. Développez Instances Aspire>postgres>Bases de données>CatalogDB>Schémas>catalogue>Tables. Cliquez ensuite avec le bouton droit sur la table Catalogue, puis sélectionnez Afficher/Modifier les données>100 premières lignes.

  4. Vous pouvez voir les données chargées par AppHost.

    Capture d’écran de l’interface pgAdmin montrant les lignes retournées à partir de la table Catalogue.

  5. Sélectionnez l’onglet du tableau de bord Ressources eShop dans votre navigateur, puis sélectionnez le point de terminaison de webapp.

  6. L’application s’ouvre et fonctionne comme avant.

  7. Pour arrêter le débogage, appuyez sur Maj+F5, ou sélectionnez Déboguer> Arrêter le débogage.

Ajouter le composant .NET Aspire MongoDB à l’application

L’application actuelle utilise Redis comme magasin de données en mémoire pour le panier d’achat d’un client. L’équipe souhaite utiliser un magasin de données plus robuste et durable pour le panier. Remplacez le cache Redis par une base de données MongoDB.

Modifier Basket.API pour utiliser MongoDB

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet Basket.API, sélectionnez Ajouter, puis sélectionnez Ajouter>package .NET Aspire.
  2. Dans la zone de Recherche, entrez MongoDB à la fin, puis appuyez sur Entrée.
  3. Sélectionnez Aspire.MongoDB.Driver, puis sélectionnez la dernière version 8.0.0.
  4. Sélectionnez Installer.
  5. Si la boîte de dialogue Aperçu des modifications s’affiche, sélectionnez Appliquer.
  6. Dans la boîte de dialogue Acceptation de la licence, sélectionnez J’accepte.@

Créer un magasin de paniers MongoDB

Le microservice panier utilise HostingExtensions pour gérer le magasin de données Redis. Remplacez le magasin de données Redis par un magasin de données MongoDB.

  1. Dans l’Explorateur de solutions, développez le projet Basket.API, puis le dossier Stockage, puis sélectionnez le fichier RedisBasketStore.cs.

    Il existe deux méthodes asynchrones, GetBasketAsync et UpdateBasketAsync, qui utilisent le cache Redis. Permet de créer des versions MongoDB de ces méthodes.

  2. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le dossier Stockage , puis sélectionnez Ajouter>Classe.

  3. Dans la boîte de dialogue Ajouter un nouvel élément , nommez le fichier MongoBasketStore.cs, puis sélectionnez Ajouter.

  4. Remplacez le code dans le fichier MongoBasketStore.cs par le code suivant :

    using eShop.Basket.API.Models;
    using MongoDB.Driver;
    using MongoDB.Driver.Linq;
    
    namespace eShop.Basket.API.Storage;
    
    public class MongoBasketStore
    {
      private readonly IMongoCollection<CustomerBasket> _basketCollection;
    
      public MongoBasketStore(IMongoClient mongoClient)
      {
        // The database name needs to match the created database in the AppHost
        _basketCollection = mongoClient.GetDatabase("BasketDB").GetCollection<CustomerBasket>("basketitems");
      }
    
      public async Task<CustomerBasket?> GetBasketAsync(string customerId)
      {
        var filter = Builders<CustomerBasket>.Filter.Eq(r => r.BuyerId, customerId);
    
        return await _basketCollection.Find(filter).FirstOrDefaultAsync();
      }
    
      public async Task<CustomerBasket?> UpdateBasketAsync(CustomerBasket basket)
      {
        var filter = Builders<CustomerBasket>.Filter.Eq(r => r.BuyerId, basket.BuyerId);
    
        var result = await _basketCollection.ReplaceOneAsync(filter, basket, new ReplaceOptions { IsUpsert = true });
    
        return result.IsModifiedCountAvailable ? basket : null;
      }
    }
    

    Le code précédent crée une classe MongoBasketStore qui fonctionne avec le modèle CustomerBasket. La collection gère les opérations CRUD pour paniers d’achat des clients dans une base de données MongoDB.

  5. Dans l’Explorateur de solutions, développez Basket.API>Extensions, puis sélectionnez le fichier HostingExtensions.cs.

  6. Remplacez le code Redis :

    builder.AddRedis("BasketStore");
    
    builder.Services.AddSingleton<RedisBasketStore>();
    

    Par le code MongoDB :

    builder.AddMongoDBClient("BasketDB");
    
    builder.Services.AddSingleton<MongoBasketStore>();
    
  7. Dans l’Explorateur de solutions, développez le dossier Grpc, puis ouvrez le fichier BasketService.cs.

  8. Modifiez la classe pour accepter un MongoBasketStore, remplacez :

    public class BasketService(RedisBasketStore basketStore) : Basket.BasketBase
    

    Par :

    public class BasketService(MongoBasketStore basketStore) : Basket.BasketBase
    

Ajouter une base de données MongoDB à AppHost

  1. Dans l’Explorateur de solutions, cliquez avec le bouton droit sur le projet eShop.AppHostet sélectionnez Ajouter>package .NET Aspire.

  2. Dans la zone de Recherche, entrez MongoDB à la fin, puis appuyez sur Entrée.

  3. Sélectionnez le package Aspire.Hosting.MongoDB, puis sélectionnez la dernière version 8.0.0.

  4. Sélectionnez Installer.

  5. Si la boîte de dialogue Aperçu des modifications s’affiche, sélectionnez Appliquer.

  6. Dans la boîte de dialogue Acceptation de la licence, sélectionnez J’accepte.@

  7. Dans l’Explorateur de solutions, développez le projet eShop.AppHost, puis ouvrez le fichier Program.cs.

  8. Dans la section Bases de données, ajoutez un composant MongoDB :

    var mongo = builder.AddMongoDB("mongo")
      .WithMongoExpress()
      .AddDatabase("BasketDB");
    

    Le code précédent crée un conteneur de base de données MongoDB, ajoute une base de données nommée BasketDB. Le code crée également un conteneur pour l’outil Mongo Express qui vous permet de gérer la base de données MongoDB.

  9. Supprimez le conteneur Redis :

    var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
    

    Le code devrait maintenant se présenter ainsi :

    // Databases
    
    var postgres = builder.AddPostgres("postgres")
        .WithEnvironment("POSTGRES_DB", "CatalogDB")
        .WithBindMount("../Catalog.API/Seed", "/docker-entrypoint-initdb.d")
        .WithPgAdmin();
    var catalogDB = postgres.AddDatabase("CatalogDB");
    
    var mongo = builder.AddMongoDB("mongo")
        .WithMongoExpress()
        .AddDatabase("BasketDB");
    
  10. Le projet Basket.API a besoin d’une référence à la nouvelle base de données MongoDB, et vous devez supprimer la référence Redis :

    var basketApi = builder.AddProject<Projects.Basket_API>("basket-api")
            .WithReference(mongo)
            .WithReference(idp);
    

Le projet Basket.API est maintenant prêt à utiliser la base de données MongoDB. Testons l’application pour voir si elle fonctionne.

Tester l'application

  1. Compilez et démarrer l’application, appuyez sur F5, ou sélectionnez Débogage>Démarrer le débogage.

    Capture d’écran du tableau de bord .NET Aspire, avec les conteneurs MongoDB mis en surbrillance.

    Vous pouvez voir les nouveaux conteneurs MongoDB, l’un pour le serveur de base de données, l’autre pour Mongo Express, dans le tableau de bord. Il existe également une nouvelle ressource MongoDBDatabase qui héberge la base de données BasketDB.

  2. Sélectionnez le point de terminaison webapp.

  3. Pour vous connecter avec les informations d’identification de l’utilisateur de test, sélectionnez l’icône de l’utilisateur en haut à droite. L’e-mail est test@example.com et le mot de passe est P@$$w0rd1.

  4. Sélectionnez Adventurer GPS Watch de la page d'accueil.

  5. Sélectionnez Ajouter au panier d’achat, vous devriez voir une exception :

    Capture d’écran montrant RpcException.

Déboguer l’application

L’application lève une exception lorsque vous essayez d’ajouter un élément au panier d’achat. Vous pouvez utiliser le tableau de bord pour vous aider à déboguer le problème.

  1. Sélectionnez l’onglet du tableau de bord Ressources eShop dans votre navigateur.

    Une capture d’écran du tableau de bord, des erreurs dans Basket.API et webapp sont mises en surbrillance.

    Le tableau de bord affiche des erreurs dans basket-api et webapp. Passez en revue les journaux pour basket-api.

  2. Pour la ressource basket-api, dans la colonne Journaux d'activité, sélectionnez Afficher.

    Capture d’écran des journaux d’activité du service basket-api.

    Il y a une exception :

    System.FormatException: Element '_id' does not match any field or property of class eShop.Basket.API.Models.CustomerBasket.
    
  3. Sélectionnez l’élément de menu Ressources, puis sélectionnez le point de terminaison mongo-mongoexpress.

  4. Dans la section Bases de données, en regard de BasketDB, sélectionnez Affichage.

  5. Dans Collections, en regard de basketitems, sélectionnez Affichage.

    Capture d’écran de Mongo Express montrant les données stockées dans la collection basketitems.

    Les documents stockés dans une base de données MongoDB ont un champ _id. Chaque document stocké dans une collection MongoDB doit avoir un champ _id unique.

  6. Pour arrêter le débogage, appuyez sur Maj+F5, ou sélectionnez Déboguer> Arrêter le débogage.

Passer en revue le code et corriger le problème

Examinons CustomerBasket et voyons si nous pouvons trouver le problème.

  1. Dans l’Explorateur de solutions, développez le dossier Basket.API>Modèles, puis ouvrez le fichier CustomerBasket.cs.

    public class CustomerBasket
    {
        public required string BuyerId { get; set; }
    
        public List<BasketItem> Items { get; set; } = [];
    }
    

    Le modèle CustomerBasket n’a pas de champ ou de propriété qui correspond au champ _id. Entity Framework tente de mapper le champ _id au modèle CustomerBasket et il ne peut pas trouver de correspondance.

  2. Mettez à jour le modèle CustomerBasket pour inclure un champ _id :

    public class CustomerBasket
    {
        /// <summary>
        /// MongoDB document identifier
        /// </summary>
        public string _id { get; set; } = "";
    
        public required string BuyerId { get; set; }
    
        public List<BasketItem> Items { get; set; } = [];
    }
    

Tester l’application fixe

  1. Pour compiler et démarrer l’application, appuyez sur F5, ou sélectionnez Débogage>Démarrer le débogage.

  2. Pour webapp, dans la colonne Points de terminaison, cliquez avec le bouton droit sur l’URL, puis sélectionnez Ouvrir le lien dans la fenêtre InPrivate.

    L’utilisation d’une fenêtre InPrivate garantit que le navigateur n’utilise pas le cookie de session précédent pour l’authentification.

  3. Pour vous connecter avec les informations d’identification de l’utilisateur de test, sélectionnez l’icône de l’utilisateur en haut à droite. L’e-mail est test@example.com et le mot de passe est P@$$w0rd1.

  4. Sélectionnez Adventurer GPS Watch de la page d'accueil.

  5. Sélectionnez Ajouter au panier d’achat.

    Capture d’écran du panier d’achat eShop fonctionnant.

    Désormais, la fonctionnalité de panier d’application Northern Mountains fonctionne.

Vous avez remplacé la base de données SQLite par une base de données PostgreSQL et le cache Redis par une base de données MongoDB. Vous avez utilisé .NET Aspire pour gérer les bases de données et explorer les données dans ces bases de données, et vous avez utilisé le tableau de bord pour vous aider à déboguer un problème avec l’application.