Exercício - Use serviços de banco de dados para persistir dados de um projeto .NET Aspire
Neste exercício, você substitui os armazenamentos de dados atuais pelo aplicativo nativo da 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 as cestas de compras do cliente. Você substitui os armazenamentos de dados existentes por PostgreSQL e MongoDB.
Pré-requisitos da instalação
Os pré-requisitos para o .NET Aspire são:
- .NET 8
- Pré-visualização do Visual Studio 2022
- 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 este link do .NET 8 e selecione o instalador correto para seu sistema operacional. Por exemplo, se você estiver usando o Windows 11 e um processador moderno, selecione o x64 .NET 8 SDK para Windows.
Após a conclusão do download, execute o instalador e siga as instruções. Em uma janela do terminal, execute o seguinte comando para verificar se a instalação foi bem-sucedida:
dotnet --version
Você deve ver o número da versão do SDK do .NET que você instalou. Por exemplo:
8.0.300-preview.24203.14
Instalar o Visual Studio 2022 Preview
Siga este link do Visual Studio 2022 Preview e selecione Baixar visualização. Após a conclusão do download, execute o instalador e siga as instruções.
Instalar o Docker Desktop
Siga este link do Docker Desktop e selecione o instalador correto para seu sistema operacional. Após a conclusão do download, execute o instalador e siga as instruções.
Abra o aplicativo Docker Desktop e aceite o contrato de serviço.
Instalar 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ê deve 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.
Clone e modifique o aplicativo Northern Mountains
Vamos usar git
para obter o aplicativo atual Northern Mountains:
Na linha de comando, navegue até uma pasta de sua escolha onde você pode trabalhar com código.
Execute o seguinte comando para clonar o aplicativo de exemplo Northern Mountains eShop :
git clone -b aspire-databases https://github.com/MicrosoftDocs/mslearn-aspire-starter
Inicie o Visual Studio e, em seguida, selecione Abrir um projeto ou solução.
Navegue até a pasta onde você clonou a eShop, abra a pasta inicial e selecione o arquivo eShop.databases.sln e, em seguida, 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 a loja de cestos.
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 Depurar > Iniciar Depuração.
Se a caixa de diálogo Iniciar área de trabalho do Docker for exibida, selecione Sim.
Quando o painel do eShop .NET Aspire aparecer, 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@$$w 0rd1.
Para parar 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 do catálogo criou o aplicativo para usar um banco de dados SQLite armazenado localmente. Essa abordagem é boa para o desenvolvimento, mas a equipe quer usar um banco de dados mais robusto para produção.
Dois projetos se conectam ao banco de dados SQLite, os projetos Catalog.Data.Manager e Catalog.API . O gerenciador de dados é usado apenas para semear 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 Pacote Add.NET> Aspire .
Na caixa Pesquisar, 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, em seguida, selecione a versão 8.0.0 mais recente.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.
Na caixa de diálogo Aceitação de 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 PostgreSQL DbContext
No Gerenciador de Soluções, expanda o projeto Catalog.API e abra o arquivo Program.cs .
Substitua o SQLite DbContext:
builder.Services.AddDbContext<CatalogDbContext>( options => options.UseSqlite(builder.Configuration.GetConnectionString("sqlconnection") ?? throw new InvalidOperationException( "Connection string 'sqlconnection' not found.")));
Com o novo PostgreSQL DbContext:
builder.AddNpgsqlDbContext<CatalogDbContext>("CatalogDB");
O aplicativo não precisa mais ler o arquivo Database.db , portanto, remova as cadeias de caracteres associadas no appsettings.json.
No Gerenciador de Soluções, em Catalog.API, selecione appsettings.json.
Exclua as
ConnectionStrings
entradas, 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 semear o banco de dados de catálogo. Você pode exibir o backup na pasta Catalog.API/Seed .
Semear o banco de dados PostgreSQL usando um volume acoplado
O projeto AppHost pode criar um contêiner de banco de dados PostgreSQL, semeá-lo com dados de um volume acoplado e, em seguida, por meio de injeção de dependência, passar referências para o Catalog.API.
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto eShop.AppHost, selecione Pacote Add.NET> Aspire .
Na caixa Pesquisar, adicione PostgreSQL ao final e pressione Enter.
À esquerda, nos resultados, selecione Aspire.Hosting.PostgreSQL.
À direita, selecione a lista suspensa de versão e, em seguida, selecione a versão 8.0.0 mais recente.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.
Na caixa de diálogo Aceitação de licença , selecione Aceito.
No Gerenciador de Soluções, expanda o projeto eShop.AppHost e abra o arquivo Program.cs .
Sob o
//Databases
comentário, 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 vincula o diretório /docker-entrypoint-initdb.d ao .. /Catalog.API/Diretório Seed . O código também cria um contêiner para a ferramenta pgAdmin que permite gerenciar o banco de dados PostgreSQL.
Passe a
catalogDB
referência para o 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 a aplicação
A utilização do .NET Aspire permitiu à sua equipa remover 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 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 Exibir/Editar Dados>Primeiras 100 Linhas.
Você pode ver os dados carregados pelo AppHost.
Selecione a guia do painel de recursos da eShop em seu navegador e, em seguida, selecione o ponto de extremidade do webapp.
O aplicativo abre e funciona como antes.
Para parar a depuração, pressione Shift+F5 ou selecione Depurar > Parar Depuração.
Adicione o componente .NET Aspire MongoDB ao aplicativo
O aplicativo atual usa o Redis como um armazenamento de dados na memória para a cesta de compras de um cliente. A equipe quer usar um armazenamento de dados mais robusto e durável para a cesta. Substitua o cache Redis por um banco de dados MongoDB.
Altere o 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, em seguida, selecione Pacote Add.NET> Aspire .
- Na caixa Pesquisar, digite MongoDB no final e pressione Enter.
- Selecione o Aspire.MongoDB.Driver e, em seguida, selecione a versão 8.0.0 mais recente.
- Selecione Instalar.
- Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.
- Na caixa de diálogo Aceitação de licença , selecione Aceito. @
Criar uma loja de cestas MongoDB
O microsserviço de cesta usa HostingExtensions
para gerenciar o armazenamento de dados Redis. Substitua o armazenamento de dados Redis por um armazenamento de dados MongoDB.
No Gerenciador de Soluções, expanda o projeto Basket.API , depois a pasta Armazenamento e selecione o arquivo RedisBasketStore.cs .
Há dois métodos
GetBasketAsync
assíncronos eUpdateBasketAsync
, que usam o cache Redis. Vamos 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 com o 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
MongoBasketStore
classe que funciona com oCustomerBasket
modelo. A coleção lida com as operações CRUD para as cestas de compras dos clientes em um banco de dados MongoDB.No Gerenciador de Soluções, expanda as Extensões Basket.API>e selecione o arquivo HostingExtensions.cs.
Substitua o código Redis:
builder.AddRedis("BasketStore"); builder.Services.AddSingleton<RedisBasketStore>();
Com o código MongoDB:
builder.AddMongoDBClient("BasketDB"); builder.Services.AddSingleton<MongoBasketStore>();
No Gerenciador de Soluções, expanda a pasta Grpc e 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 MongoDB ao AppHost
No Gerenciador de Soluções, clique com o botão direito do mouse no projeto eShop.AppHost e selecione Add.NET> Aspire package.
Na caixa Pesquisar, digite MongoDB no final e pressione Enter.
Selecione o pacote Aspire.Hosting.MongoDB e, em seguida, selecione a versão 8.0.0 mais recente.
Selecione Instalar.
Se a caixa de diálogo Visualizar alterações for exibida, selecione Aplicar.
Na caixa de diálogo Aceitação de licença , selecione Aceito. @
No Gerenciador de Soluções, expanda o projeto eShop.AppHost e 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 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 MongoDB.
Exclua o contêiner Redis:
var basketStore = builder.AddRedis("BasketStore").WithRedisCommander();
O código agora deve ter esta aparência:
// 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 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 MongoDB. Vamos testar o aplicativo para ver se ele funciona.
Testar a aplicação
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 painel. Há também um novo recurso MongoDBDatabase que hospeda o banco de dados BasketDB.
Selecione o ponto de extremidade do webapp .
Para entrar com as credenciais de usuário de teste, selecione o ícone de usuário no canto superior direito. O e-mail é test@example.com e a senha é P@$$w 0rd1.
Selecione o Relógio GPS Aventureiro na página inicial.
Selecione Adicionar ao carrinho de compras, você 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 painel para ajudar a depurar o problema.
Selecione a guia do painel de recursos da eShop no seu navegador.
O painel mostra erros na cesta-api e no webapp. Revise os logs para a 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, em seguida, selecione o ponto de extremidade mongo-mongoexpress .
Na seção Bancos de dados, ao lado de BasketDB, selecione View.
Em Coleções, ao lado de itens da cesta, selecione Exibir.
Os documentos armazenados em um MongoDB têm um campo _id . Cada documento armazenado em uma coleção MongoDB deve ter um campo _id exclusivo.
Para parar a depuração, pressione Shift+F5 ou selecione Depurar > Parar Depuração.
Revise o código e corrija o problema
Vamos olhar para o CustomerBasket, e ver se podemos encontrar o problema.
No Gerenciador de Soluções, expanda a pasta Modelos Basket.API> 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 ou propriedade que corresponda ao campo _id . A estrutura de entidade está tentando mapear o campo _id para o modelo CustomerBasket e não consegue encontrar uma correspondência.
Atualize o
CustomerBasket
modelo 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 o aplicativo Web, 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 de usuário de teste, selecione o ícone de usuário no canto superior direito. O e-mail é test@example.com e a senha é P@$$w 0rd1.
Selecione o Relógio GPS Aventureiro na página inicial.
Selecione Adicionar ao carrinho de compras.
A funcionalidade de cesta de aplicativos Northern Mountains 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 painel para ajudar a depurar um problema com o aplicativo.