Exercício – Usar serviços de banco de dados para persistir dados de um projeto do .NET Aspire
Neste exercício, você substitui os armazenamentos de dados atuais para o aplicativo nativo de nuvem em desenvolvimento da sua empresa. No momento, o aplicativo usa um banco de dados SQLite armazenado localmente para dados de catálogo e um cache Redis na memória para carrinhos de compras do cliente. Substitua os armazenamentos de dados existentes por PostgreSQL e MongoDB.
Instalar pré-requisitos
Os pré-requisitos para o .NET Aspire são:
- .NET 8
- Visual Studio 2022 Preview
- Docker Desktop ou Podman
- Carga de trabalho do .NET Aspire no Visual Studio
Se você já tiver os pré-requisitos instalados, poderá pular para clonar o aplicativo existente.
Instalar o .NET 8
Siga esse link do .NET 8 e selecione o instalador correto para o seu sistema operacional. Por exemplo, se você estiver usando o Windows 11 e um processador moderno, selecione x64 .NET 8 SDK para Windows.
Após a conclusão do download, execute o instalador e siga as instruções. Em uma janela de terminal, execute o seguinte comando para verificar se a instalação foi bem-sucedida:
dotnet --version
Você deverá ver o número da versão do SDK do .NET instalado. Por exemplo:
8.0.300-preview.24203.14
Instale a versão prévia do Visual Studio 2022
Siga esse link Visual Studio 2022 Preview e selecione Baixar versão prévia. Após a conclusão do download, execute o instalador e siga as instruções.
Instalar o Docker Desktop
Siga esse link Docker Desktop e selecione o instalador correto para o seu sistema operacional. Após a conclusão do download, execute o instalador e siga as instruções.
Abra o aplicativo do Docker Desktop e aceite o contrato de serviço.
Instale a carga de trabalho do .NET Aspire no Visual Studio
Instale a carga de trabalho do .NET Aspire usando a CLI do .NET:
Abra um terminal.
Instale as cargas de trabalho do .NET Aspire com estes comandos:
dotnet workload update dotnet workload install aspire dotnet workload list
Você deverá ver os detalhes da carga de trabalho do .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.
Clonar e modificar o aplicativo Northern Mountains
Vamos usar git
para obter o aplicativo Northern Mountains atual:
Na linha de comando, navegue até uma pasta de sua escolha onde você possa trabalhar com o código.
Execute o seguinte comando para clonar o aplicativo de amostra Northern Mountains eShop:
git clone -b aspire-databases https://github.com/MicrosoftDocs/mslearn-aspire-starter
Inicie o Visual Studio e selecione Abrir um projeto ou solução.
Navegue até a pasta onde você clonou o eShop, abra a pasta iniciar e selecione o arquivo eShop.databases.sln e selecione Abrir.
No Gerenciador de Soluções, expanda o projeto eShop.AppHost e abra 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");
O código anterior mostra a configuração atual do aplicativo. O aplicativo usa um Cache Redis para o repositório de carrinhos.
Explore o restante do aplicativo, concentre-se nos projetos Catalog.Data.Manager e Catalog.API e veja como eles usam um banco de dados SQLite armazenado localmente.
Para iniciar o aplicativo, pressione F5 ou selecione Depuração > Iniciar Depuração.
Se a caixa de diálogo Iniciar Docker Desktop aparecer, selecione Sim.
Quando o dashboard do eShop .NET Aspire for exibido, para o recurso webapp, selecione o ponto de extremidade seguro:
O aplicativo é aberto em um navegador. Você pode explorar o aplicativo e ver como ele funciona.
As credenciais do usuário de teste são test@example.com e P@$$w0rd1.
Para interromper a depuração, pressione Shift+F5 ou selecione Depurar > Parar Depuração.
Adicionar um componente .NET Aspire PostgreSQL
A equipe responsável pelos microsserviços de catálogo criou o aplicativo para usar um banco de dados SQLite armazenado localmente. Essa abordagem é boa para o desenvolvimento, mas a equipe deseja usar um banco de dados mais robusto para produção.
Dois projetos se conectam ao banco de dados SQLite, o Catalog.Data.Manager e o Catalog.API. O gerenciador de dados é usado apenas para propagar o banco de dados com dados, portanto, você deve se concentrar no projeto Catalog.API.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto Catalog.API, selecione Adicionar>Pacote do .NET Aspire.
Na caixa Pesquisa, adicione Npgsql.EntityFramework ao final e pressione Enter.
À esquerda, nos resultados, selecione Aspire.Npgsql.EntityFrameworkCore.PostgreSQL.
À direita, selecione a lista suspensa de versão e selecione a última versão 8.0.0.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.
No Gerenciador de Soluções, selecione o projeto Catalog.API para exibir o conteúdo do arquivo Catalog.API.csproj.
Exclua o
PackageReference
para Microsoft.EntityFrameworkCore.Sqlite:<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.3" />
Registrar o novo DbContext do PostgreSQL
No Gerenciador de Soluções, expanda o projeto Catalog.API e, em seguida, abra o arquivo Program.cs.
Substitua o DbContext do SQLite:
builder.Services.AddDbContext<CatalogDbContext>( options => options.UseSqlite(builder.Configuration.GetConnectionString("sqlconnection") ?? throw new InvalidOperationException( "Connection string 'sqlconnection' not found.")));
Por um novo DbContext do PostgreSQL:
builder.AddNpgsqlDbContext<CatalogDbContext>("CatalogDB");
O aplicativo não precisa mais ler o arquivo Database.db. Portanto, remova as cadeias de caracteres associadas em appsettings.json.
No Gerenciador de Soluções, em Catalog.API, selecione appsettings.json.
Exclua as entradas de
ConnectionStrings
, o arquivo agora tem esta aparência:{ "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/" } }
Clique com o botão direito do mouse no projeto Catalog.Data.Manager e selecione Remover.
Na caixa de diálogo, selecione OK.
A equipe de banco de dados cria um backup de banco de dados PostgreSQL para você usar para criar e propagar o banco de dados do catálogo. Você pode exibir o backup na pasta Catalog.API/Seed.
Propagar o banco de dados PostgreSQL usando um volume associado
O projeto AppHost pode criar um contêiner de banco de dados PostgreSQL, semeá-lo com dados de um volume associado e, em seguida, por meio de referências de passagem de injeção de dependência para o Catalog.API.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto eShop.AppHost, selecione Adicionar>Pacote do .NET Aspire.
Na caixa Pesquisa, adicione PostgreSQL ao final e pressione Enter.
À esquerda, nos resultados, selecione Aspire.Hosting.PostgreSQL.
À direita, selecione a lista suspensa de versão e selecione a última versão 8.0.0.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.
No Gerenciador de Soluções, expanda o projeto eShop.AppHost e, em seguida, abra o arquivo Program.cs.
Abaixo do comentário
//Databases
, adicione o seguinte código:// 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");
O código anterior cria um contêiner de banco de dados PostgreSQL, adiciona um banco de dados chamado CatalogDB e associa o diretório /docker-entrypoint-initdb.d ao diretório ../Catalog.API/Seed. O código também cria um contêiner para a ferramenta pgAdmin que permite gerenciar o banco de dados PostgreSQL.
Passe a referência
catalogDB
ao projeto Catalog.API adicionando.WithReference(catalogDB)
, o código agora é:// API Apps var catalogApi = builder.AddProject<Projects.Catalog_API>("catalog-api") .WithReference(catalogDB);
O projeto Catalog.Data.Manager não é mais necessário, portanto, remova o projeto do AppHost. Exclua este código:
// DB Manager Apps builder.AddProject<Projects.Catalog_Data_Manager>("catalog-db-mgr");
Testar o aplicativo
O uso do .NET Aspire permitiu que sua equipe removesse um projeto inteiro. Além disso, a API de catálogo só precisa de uma única linha de código para adicionar o contexto do banco de dados PostgresSQL. A injeção de dependência e a descoberta de serviço do AppHost significam que nenhuma outra alteração de código é necessária para permitir que a API se conecte ao novo banco de dados.
Compile e inicie o aplicativo, pressione F5 ou selecione Depurar > Iniciar Depuração.
Há dois novos contêineres no painel que hospedam o servidor de banco de dados PostgreSQL e a ferramenta pgAdmin. Há também um recurso de banco de dados PostgreSQL que hospeda o banco de dados do CatalogDB.
Use pgAdmin para se conectar ao banco de dados PostgreSQL e explorar os dados. Selecione o ponto de extremidade postgres pgadmin.
Expanda Instâncias do Aspire>postgres>Bancos de Dados>CatalogDB>Esquemas>catálogo>Tabelas. Em seguida, clique com o botão direito do mouse na tabela Catálogo e selecione Ver/Editar Dados>Primeiras 100 Linhas.
Você pode ver os dados carregados pelo AppHost.
Selecione a guia do dashboard Recursos de eShop no navegador e selecione o ponto de extremidade webapp.
O aplicativo é aberto e funciona como antes.
Para interromper a depuração, pressione Shift+F5 ou selecione Depurar > Parar Depuração.
Adicionar o componente .NET Aspire MongoDB ao aplicativo
O aplicativo atual usa o Redis como um armazenamento de dados na memória para o carrinho de compras de um cliente. A equipe deseja usar um armazenamento de dados mais robusto e durável para o carrinho. Substitua o cache Redis por um banco de dados do MongoDB.
Alterar a Basket.API para usar o MongoDB
- No Gerenciador de Soluções, clique com o botão direito do mouse no projeto Basket.API, selecione Adicionar e depois Adicionar>Pacote do .NET Aspire.
- Na caixa Search, insira MongoDB no final e pressione Enter.
- Selecione Aspire.MongoDB.Driver e, em seguida, selecione a versão mais recente 8.0.0.
- Selecione Instalar.
- Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
- Na caixa de diálogo Aceitação da Licença, selecione Aceito.@
Criar um repositório de carrinhos do MongoDB
O microsserviço de carrinho usa HostingExtensions
para gerenciar o armazenamento de dados do Redis. Substitua o repositório de dados do Redis por um armazenamento de dados do MongoDB.
No Gerenciador de Soluções, expanda o projeto Basket.API e depois a pasta Storage. Em seguida, selecione o arquivo RedisBasketStore.cs.
Há dois métodos assíncronos,
GetBasketAsync
eUpdateBasketAsync
, que usam o Cache Redis. Permite criar versões do MongoDB desses métodos.No Gerenciador de Soluções, clique com o botão direito do mouse na pasta Armazenamento e selecione Adicionar>Classe.
Na caixa de diálogo Adicionar Novo Item, nomeie o arquivo MongoBasketStore.cs e selecione Adicionar.
Substitua o código no arquivo MongoBasketStore.cs pelo seguinte código:
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; } }
O código anterior cria uma classe
MongoBasketStore
que funciona com o modelo deCustomerBasket
. A coleção manipula as operações CRUD para as cestas de compras dos clientes em um banco de dados do MongoDB.No Gerenciador de Soluções, expanda Basket.API>Extensões e selecione o arquivo HostingExtensions.cs.
Substitua o código Redis:
builder.AddRedis("BasketStore"); builder.Services.AddSingleton<RedisBasketStore>();
Com o código do MongoDB:
builder.AddMongoDBClient("BasketDB"); builder.Services.AddSingleton<MongoBasketStore>();
No Gerenciador de Soluções, expanda a pasta Grpc e, em seguida, abra o arquivo BasketService.cs.
Altere a classe para aceitar um
MongoBasketStore
, substitua:public class BasketService(RedisBasketStore basketStore) : Basket.BasketBase
Por:
public class BasketService(MongoBasketStore basketStore) : Basket.BasketBase
Adicionar um banco de dados do MongoDB ao AppHost
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto eShop.AppHost e selecione Adicionar>Pacote do .NET Aspire.
Na caixa Search, insira MongoDB no final e pressione Enter.
Selecione o pacote Aspire.Hosting.MongoDB e selecione a versão mais recente 8.0.0.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações aparecer, selecione Aplicar.
Na caixa de diálogo Aceitação da Licença, selecione Aceito.@
No Gerenciador de Soluções, expanda o projeto eShop.AppHost e, em seguida, abra o arquivo Program.cs.
Na seção Bancos de Dados, adicione um componente do MongoDB:
var mongo = builder.AddMongoDB("mongo") .WithMongoExpress() .AddDatabase("BasketDB");
O código anterior cria um contêiner de banco de dados do MongoDB, adiciona um banco de dados chamado BasketDB. O código também cria um contêiner para a ferramenta Mongo Express que permite gerenciar o banco de dados do MongoDB.
Exclua o contêiner do Redis:
var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
Agora, o código deve se parecer com este:
// 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");
O projeto Basket.API precisa de uma referência ao novo banco de dados do MongoDB, e você deve remover a referência Redis:
var basketApi = builder.AddProject<Projects.Basket_API>("basket-api") .WithReference(mongo) .WithReference(idp);
O projeto Basket.API agora está pronto para usar o banco de dados do MongoDB. Vamos testar o aplicativo para ver se ele funciona.
Testar o aplicativo
Compile e inicie o aplicativo, pressione F5 ou selecione Depurar > Iniciar Depuração.
Você pode ver os novos contêineres do MongoDB, um para o servidor de banco de dados e outro para o Mongo Express, no dashboard. Há também um novo recurso MongoDBDatabase que hospeda o banco de dados BasketDB.
Selecione o ponto de extremidade webapp.
Para entrar com as credenciais do usuário de teste, selecione o ícone de usuário no canto superior direito. O email é test@example.com e a senha é P@$$w 0rd1.
Selecione o Adventurer GPS Watch na home page.
Selecione Adicionar à sacola de compras. Você deverá ver uma exceção:
Depurar o aplicativo
O aplicativo está lançando uma exceção quando você tenta adicionar um item ao carrinho de compras. Você pode usar o dashboard para ajudar a depurar o problema.
Selecione a guia do dashboard Recursos de eShop no navegador.
O painel mostra erros em basket-api e webapp. Analise os logos da basket-api.
Para o recurso basket-api, na coluna Logs, selecione Exibir.
Há uma exceção:
System.FormatException: Element '_id' does not match any field or property of class eShop.Basket.API.Models.CustomerBasket.
Selecione o item de menu Recursos e depois o ponto de extremidade mongo-mongoexpress.
Na seção Bancos de dados, ao lado de BasketDB, selecione Exibir.
Em Coleções, ao lado de basketitems, selecione Exibir.
Os documentos armazenados em um MongoDB têm um campo _id. Cada documento armazenado em uma coleção do MongoDB deve ter um campo de _id exclusivo.
Para interromper a depuração, pressione Shift+F5 ou selecione Depurar > Parar Depuração.
Examine o código e corrija o problema
Vamos examinar o CustomerBasket e ver se podemos encontrar o problema.
No Gerenciador de Soluções, expanda a pasta Basket.API>Modelos e abra o arquivo CustomerBasket.cs.
public class CustomerBasket { public required string BuyerId { get; set; } public List<BasketItem> Items { get; set; } = []; }
O modelo CustomerBasket não tem um campo nem uma propriedade que corresponda ao campo _id. A Entity Framework está tentando mapear o campo _id para o modelo CustomerBasket e não consegue encontrar uma correspondência.
Atualize o modelo
CustomerBasket
para incluir um campo _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; } = []; }
Testar o aplicativo fixo
Para compilar e iniciar o aplicativo, pressione F5 ou selecione Depurar > Iniciar Depuração.
Para webapp, na coluna Pontos de extremidade, clique com o botão direito do mouse na URL e selecione Abrir link na janela InPrivate.
O uso de uma janela InPrivate garante que o navegador não use o cookie de sessão anterior para autenticação.
Para entrar com as credenciais do usuário de teste, selecione o ícone de usuário no canto superior direito. O email é test@example.com e a senha é P@$$w 0rd1.
Selecione o Adventurer GPS Watch na home page.
Selecione Adicionar à sacola de compras.
A funcionalidade do carrinho do aplicativo Northern Mountain agora está funcionando.
Você substituiu com êxito o banco de dados SQLite por um banco de dados PostgreSQL e o Cache Redis por um banco de dados MongoDB. Você usou o .NET Aspire para gerenciar os bancos de dados e explorar os dados neles e usou o dashboard para ajudar a depurar um problema com o aplicativo.