Övning – Använda databastjänster för att spara data från ett .NET Aspire-projekt

Slutförd

I den här övningen ersätter du de aktuella datalagren för företagets molnbaserade app under utveckling. För närvarande använder appen en lokalt lagrad SQLite-databas för katalogdata och en minnesintern Redis-cache för kundens kundkorgar. Du ersätter befintliga datalager med PostgreSQL och MongoDB.

Installera förutsättningar

Förutsättningarna för .NET Aspire är:

  • .NET 8
  • Förhandsversion av Visual Studio 2022
  • Docker Desktop eller Podman
  • .NET Aspire-arbetsbelastning i Visual Studio

Om du redan har installerat förhandskraven kan du gå vidare till kloning av den befintliga appen.

Installera .NET 8

Följ den här länken .NET 8 och välj rätt installationsprogram för operativsystemet. Om du till exempel använder Windows 11 och en modern processor väljer du X64 .NET 8 SDK för Windows.

När nedladdningen är klar kör du installationsprogrammet och följer anvisningarna. I ett terminalfönster kör du följande kommando för att kontrollera att installationen lyckades:

dotnet --version

Du bör se versionsnumret för .NET SDK som du har installerat. Till exempel:

8.0.300-preview.24203.14

Installera Visual Studio 2022 Preview

Följ den här länken Visual Studio 2022 Preview och välj Hämta förhandsversion. När nedladdningen är klar kör du installationsprogrammet och följer anvisningarna.

Installera Docker Desktop

Följ den här länken Docker Desktop och välj rätt installationsprogram för operativsystemet. När nedladdningen är klar kör du installationsprogrammet och följer anvisningarna.

Öppna Docker Desktop-programmet och godkänn tjänstavtalet.

Installera .NET Aspire-arbetsbelastningen i Visual Studio

Installera .NET Aspire-arbetsbelastningen med .NET CLI:

  1. Öppna en terminal.

  2. Installera .NET Aspire-arbetsbelastningarna med följande kommandon:

    dotnet workload update
    dotnet workload install aspire
    dotnet workload list
    

    Du bör se information om .NET Aspire-arbetsbelastningen.

     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.
    

Klona och ändra appen Northern Mountains

Vi använder git för att hämta den aktuella northern mountains-appen:

  1. På kommandoraden bläddrar du till en mapp där du kan arbeta med kod.

  2. Kör följande kommando för att klona Northern Mountains eShop exempelprogram:

    git clone -b aspire-databases https://github.com/MicrosoftDocs/mslearn-aspire-starter
    
  3. Starta Visual Studio och välj sedan Öppna ett projekt eller en lösning.

  4. Bläddra till mappen där du klonade eShop, öppna mappen start och välj filen eShop.databases.sln, och välj sedan Öppna.

  5. I Solution Explorerexpanderar du projektet eShop.AppHost och öppnar sedan 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");
    

    Föregående kod visar den aktuella konfigurationen för appen. Appen använder en Redis-cache för korgbutiken.

  6. Utforska resten av appen, fokusera på projekten Catalog.Data.Manager och Catalog.API och se hur de använder en lokalt lagrad SQLite-databas.

  7. Starta appen genom att trycka på F5 eller välja Felsökning > Starta felsökning.

  8. Om dialogrutan Starta Docker Desktop visas väljer du Ja.

  9. När instrumentpanelen för eShop .NET Aspire visas, väljer du den säkra slutpunkten för resursen i webbappen.

    En skärmbild av instrumentpanelen eShop .NET Aspire. Webbappens slutpunkt är markerad.

  10. Appen öppnas i en webbläsare. Du kan utforska appen och se hur den fungerar.

    En skärmbild av eShop-startsidan.

    Testanvändarens autentiseringsuppgifter är test@example.com och P@$$w 0rd1.

  11. Om du vill sluta felsöka trycker du på Skift+F5eller väljer Felsökning > Sluta felsöka.

Lägga till en .NET Aspire PostgreSQL-komponent

Teamet som ansvarar för katalogmikrotjänsterna skapade appen för att använda en lokalt lagrad SQLite-databas. Den här metoden passar bra för utveckling, men teamet vill använda en mer robust databas för produktion.

Två projekt ansluter till SQLite-databasen, Catalog.Data.Manager och Catalog.API projekt. Datahanteraren används bara för att skicka data till databasen, så du bör fokusera på projektet Catalog.API.

  1. I Solution Explorerhögerklickar du på projektet Catalog.API och väljer Lägg till>.NET Aspire-paket.

  2. I rutan Sök lägger du till Npgsql.EntityFramework i slutet och trycker på Retur.

  3. I resultatet till vänster väljer du Aspire.Npgsql.EntityFrameworkCore.PostgreSQL.

  4. Till höger väljer du listrutan version och väljer sedan den senaste versionen 8.0.0.

  5. Välj Installera.

  6. Om dialogrutan Förhandsgranska ändringar visas väljer du Använd.

  7. I dialogrutan Licensgodkännande väljer du Jag accepterar.

  8. I Solution Explorerväljer du projektet Catalog.API för att visa innehållet i filen Catalog.API.csproj.

  9. Ta bort PackageReference för Microsoft.EntityFrameworkCore.Sqlite:

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

Registrera den nya PostgreSQL DbContext

  1. I Solution Explorerexpanderar du projektet Catalog.API och öppnar sedan filen Program.cs.

  2. Ersätt SQLite DbContext:

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

    Med den nya PostgreSQL DbContext:

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

    Appen behöver inte längre läsa Database.db-filen, så ta bort de associerade strängarna i appsettings.json.

  3. I Solution Explorerväljer du appsettings.jsonunder Catalog.API.

  4. Ta bort ConnectionStrings-posterna, nu ser filen ut så här:

    {
      "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. Högerklicka på projektet Catalog.Data.Manager och välj sedan Ta bort.

  6. I dialogrutan väljer du OK.

Databasteamet skapar en PostgreSQL-databassäkerhetskopia som du kan använda för att skapa och seeda katalogdatabasen. Du kan visa säkerhetskopian i mappen Catalog.API/Seed.

Seeda PostgreSQL-databasen med hjälp av en bunden volym

Projektet AppHost kan skapa en PostgreSQL-databascontainer, skicka data från en bunden volym och sedan skicka referenser via beroendeinmatning till Catalog.API.

  1. I Solution Explorerhögerklickar du på projektet eShop.AppHost och väljer Lägg till>.NET Aspire-paket.

  2. I rutan Search lägger du till PostgreSQL- i slutet och trycker på Retur.

  3. I resultatet till vänster väljer du Aspire.Hosting.PostgreSQL.

  4. Till höger väljer du listrutan version och väljer sedan den senaste versionen 8.0.0.

  5. Välj Installera.

  6. Om dialogrutan Förhandsgranska ändringar visas väljer du Använd.

  7. I dialogrutan Licensgodkännande väljer du Jag accepterar.

  8. I Solution Explorerexpanderar du projektet eShop.AppHost och öppnar sedan filen Program.cs.

  9. Under kommentaren //Databases lägger du till följande kod:

    // 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");
    

    Föregående kod skapar en PostgreSQL-databascontainer, lägger till en databas med namnet CatalogDBoch binder katalogen /docker-entrypoint-initdb.d till .. /Catalog.API/Seed-katalog. Koden skapar också en container för pgAdmin-verktyget som gör att du kan hantera PostgreSQL-databasen.

  10. Skicka catalogDB-referensen till projektet Catalog.API genom att lägga till .WithReference(catalogDB), koden är nu:

    // API Apps
    
    var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api")
      .WithReference(catalogDB); 
    
  11. Projektet Catalog.Data.Manager behövs inte längre, så ta bort projektet från AppHost-. Ta bort den här koden:

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

Testa appen

Med hjälp av .NET Aspire kunde ditt team ta bort ett helt projekt. Katalog-API:et behöver dessutom bara en enda kodrad för att lägga till PostgresSQL-databaskontexten. Beroendeinmatning och tjänstidentifiering från AppHost innebär att inga andra kodändringar behövs för att API:et ska kunna ansluta till den nya databasen.

  1. Kompilera och starta appen, tryck på F5eller välj Felsök > Starta felsökning.

    En skärmbild som visar den uppdaterade .NET Aspire-instrumentpanelen med de två nya PostgreSQL-containrarna markerade.

    Det finns två nya containrar på instrumentpanelen som är värd för PostgreSQL-databasservern och pgAdmin-verktyget. Det finns också en PostgreSQL-databasresurs som är värd för CatalogDB-databasen.

  2. Använd pgAdmin för att ansluta till PostgreSQL-databasen och utforska data. Välj postgres pgadmin slutpunkt.

    En skärmbild av pgAdmin-gränssnittet som markerar navigeringen till tabellen Katalog.

  3. Expandera Aspire-instanser>postgres>databaser>CatalogDB>Schemas>katalog>tabeller. Högerklicka sedan på tabellen Catalog och välj Visa/Redigera Data>Första 100 Raderna.

  4. Du kan se de data som läses in av AppHost.

    En skärmbild av pgAdmin-gränssnittet som visar de returnerade raderna från tabellen Katalog.

  5. Välj fliken eShop-resurser flik i webbläsaren och välj sedan webbappens slutpunkt.

  6. Appen öppnas och fungerar som tidigare.

  7. Om du vill sluta felsöka trycker du på Skift+F5eller väljer Felsökning > Sluta felsöka.

Lägg till .NET Aspire MongoDB-komponenten i appen

Den aktuella appen använder Redis som ett minnesinternt datalager för en kunds varukorg. Teamet vill använda ett mer robust och hållbart datalager för korgen. Ersätt Redis-cachen med en MongoDB-databas.

Ändra Basket.API till att använda MongoDB

  1. I Solution Explorerhögerklickar du på projektet Basket.API, väljer Lägg tilloch väljer sedan Lägg till>.NET Aspire-paket.
  2. I rutan Sök anger du MongoDB i slutet och trycker på Retur.
  3. Välj Aspire.MongoDB.Driveroch välj sedan den senaste 8.0.0 version.
  4. Välj Installera.
  5. Om dialogrutan Förhandsgranska ändringar visas väljer du Använd.
  6. I dialogrutan Licensgodkännande väljer du Jag accepterar. @

Skapa ett MongoDB-korglager

Korgmikrotjänsten använder HostingExtensions för att hantera Redis-datalagret. Ersätt Redis-datalagret med ett MongoDB-datalager.

  1. I Solution Explorerexpanderar du projektet Basket.API, sedan mappen Storage och väljer sedan filen RedisBasketStore.cs.

    Det finns två asynkrona metoder, GetBasketAsync och UpdateBasketAsync, som använder Redis-cachen. Låt oss skapa MongoDB-versioner av dessa metoder.

  2. I Solution Explorerhögerklickar du på mappen Storage och väljer sedan Lägg till>klass.

  3. I dialogrutan Lägg till nytt objekt namnger du filen MongoBasketStore.csoch väljer sedan Lägg till.

  4. Ersätt koden i filen MongoBasketStore.cs med följande kod:

    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;
      }
    }
    

    Föregående kod skapar en MongoBasketStore-klass som fungerar med CustomerBasket-modellen. Samlingen hanterar CRUD-åtgärderna för kundernas kundkorgar i en MongoDB-databas.

  5. I Solution Explorerexpanderar du Basket.API>Extensions och väljer sedan filen HostingExtensions.cs.

  6. Ersätt Redis-koden:

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

    Med MongoDB-koden:

    builder.AddMongoDBClient("BasketDB");
    
    builder.Services.AddSingleton<MongoBasketStore>();
    
  7. I Solution Explorerexpanderar du mappen Grpc och öppnar sedan filen BasketService.cs.

  8. Ändra klassen så att den accepterar en MongoBasketStore, ersätt:

    public class BasketService(RedisBasketStore basketStore) : Basket.BasketBase
    

    Med:

    public class BasketService(MongoBasketStore basketStore) : Basket.BasketBase
    

Lägga till en MongoDB-databas i AppHost

  1. I Solution Explorerhögerklickar du på projektet eShop.AppHost och väljer Lägg till>.NET Aspire-paket.

  2. I rutan Sök skriver du MongoDB i slutet och trycker på Enter.

  3. Välj paketet Aspire.Hosting.MongoDB och välj sedan den senaste version 8.0.0.

  4. Välj Installera.

  5. Om dialogrutan Förhandsgranska ändringar visas väljer du Använd.

  6. I dialogrutan Licensgodkännande väljer du Jag accepterar. @

  7. I Solution Explorerexpanderar du projektet eShop.AppHost och öppnar sedan filen Program.cs.

  8. I avsnittet Databaser lägger du till en MongoDB-komponent:

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

    Den tidigare koden skapar en MongoDB-databascontainer, lägger till en databas med namnet BasketDB. Koden skapar också en container för Mongo Express-verktyget som gör att du kan hantera MongoDB-databasen.

  9. Ta bort Redis-containern:

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

    Koden bör nu se ut så här:

    // 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. Basket.API-projektet behöver en referens till den nya MongoDB-databasen och du bör ta bort Redis-referensen:

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

Projektet Basket.API är nu redo att använda MongoDB-databasen. Nu ska vi testa appen för att se om den fungerar.

Testa appen

  1. Kompilera och starta appen, tryck på F5eller välj Felsök > Starta felsökning.

    En skärmbild av .NET Aspire-instrumentpanelen med MongoDB-containrarna markerade.

    Du kan se de nya MongoDB-containrarna, en för databasservern den andra för Mongo Express, på instrumentpanelen. Det finns också en ny MongoDBDatabase resurs som är värd för databasen BasketDB.

  2. Välj slutpunkten för webbappen .

  3. Om du vill logga in med testanvändarautentiseringsuppgifterna väljer du användarikonen längst upp till höger. E-postmeddelandet är test@example.com och lösenordet är P@$$w 0rd1.

  4. Välj Adventurer GPS Watch från startsidan.

  5. Välj Lägg till i shoppingväskan, så bör du se ett undantagsmeddelande.

    En skärmbild som visar RpcException.

Felsöka appen

Appen utlöser ett undantag när du försöker lägga till ett objekt i varukorgen. Du kan använda instrumentpanelen för att felsöka problemet.

  1. Välj fliken eShop-resurser kontrollpanel i webbläsaren.

    En skärmbild av instrumentpanelen där fel i Basket.API och webbappen är markerade.

    Instrumentpanelen visar fel i basket-api och webbapp. Granska loggarna för basket-api.

  2. För resursen basket-api väljer du Viewi kolumnen Logs .

    En skärmbild av loggarna för basket-api-tjänsten.

    Det finns ett undantag:

    System.FormatException: Element '_id' does not match any field or property of class eShop.Basket.API.Models.CustomerBasket.
    
  3. Välj menyalternativet Resurser och välj sedan mongo-mongoexpress slutpunkt.

  4. I avsnittet Databases väljer du Viewbredvid BasketDB.

  5. I Collectionsväljer du Viewbredvid basketitems.

    En skärmbild av Mongo Express som visar data som lagras i samlingen basketitems.

    Dokument som lagras i en MongoDB har ett _id fält. Varje dokument som lagras i en MongoDB-samling måste ha ett unikt _id fält.

  6. Om du vill sluta felsöka trycker du på Skift+F5eller väljer Felsökning > Sluta felsöka.

Granska koden och åtgärda problemet

Nu ska vi titta på CustomerBasket-och se om vi kan hitta problemet.

  1. I Solution Explorerexpanderar du mappen Basket.API>Models och öppnar sedan filen CustomerBasket.cs.

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

    CustomerBasket-modellen har inte ett fält eller en egenskap som matchar _id fältet. Entitetsramverket försöker mappa fältet _id till CustomerBasket- modell, och det går inte att hitta någon matchning.

  2. Uppdatera CustomerBasket-modellen så att den innehåller ett _id fält:

    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; } = [];
    }
    

Testa den åtgärdade appen

  1. Om du vill kompilera och starta appen trycker du på F5eller väljer Felsökning > Starta felsökning.

  2. För -webbappeni kolumnen Slutpunkter högerklickar du på URL:en och väljer sedan Öppna länk i InPrivate-fönstret.

    Om du använder ett InPrivate-fönster ser du till att webbläsaren inte använder den föregående sessionscookien för autentisering.

  3. Om du vill logga in med testanvändarautentiseringsuppgifterna väljer du användarikonen längst upp till höger. E-postmeddelandet är test@example.com och lösenordet är P@$$w 0rd1.

  4. Välj Adventurer GPS Watch från startsidan.

  5. Välj Lägg till i shoppingväskan.

    En skärmbild av eShop-varukorgen.

    Appkorgsfunktionerna i Northern Mountains fungerar nu.

Du har ersatt SQLite-databasen med en PostgreSQL-databas och Redis-cachen med en MongoDB-databas. Du använde .NET Aspire för att hantera databaserna och utforska data i dem, och du använde instrumentpanelen för att felsöka ett problem med appen.