Exercício – Acessar dados de um componente Blazor
As pizzas codificadas atualmente no aplicativo precisam ser substituídas por um banco de dados. Você pode usar o Microsoft Entity Framework para adicionar conexões a fontes de dados. Neste aplicativo, usamos um banco de dados SQLite para armazenar as pizzas.
Neste exercício, você adiciona pacotes para dar suporte à funcionalidade do banco de dados, conecta classes a um banco de dados de back-end e adiciona uma classe auxiliar para carregar previamente os dados das pizzas da empresa.
Adicionar pacotes que dão suporte ao acesso ao banco de dados
Interrompa o aplicativo se ele ainda estiver em execução.
No Visual Studio Code, selecione Terminal>Novo Terminal.
No novo terminal, defina sua localização para o diretório BlazingPizza .
cd BlazingPizzaExecute estes comandos para adicionar os pacotes Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite e System.Net.Http.Json :
dotnet add package Microsoft.EntityFrameworkCore --version 9.0.0 dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 9.0.0 dotnet add package System.Net.Http.Json --version 9.0.0Esses comandos adicionam referências de pacote ao arquivo BlazingPizza.csproj:
<ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0-*" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="9.0.0-*" /> <PackageReference Include="System.Net.Http.Json" Version="9.0.0-*" /> </ItemGroup>
Adicionar um contexto de banco de dados
No Visual Studio Code, crie uma nova pasta na pasta BlazingPizza . Nomeie-o Dados.
Na pasta Dados , crie um novo arquivo chamado PizzaStoreContext.cs.
No novo arquivo, insira este código para a classe:
using Microsoft.EntityFrameworkCore; namespace BlazingPizza.Data; public class PizzaStoreContext : DbContext { public PizzaStoreContext(DbContextOptions options) : base(options) { } public DbSet<PizzaSpecial> Specials { get; set; } }Essa classe cria um contexto de banco de dados que podemos usar para registrar um serviço de banco de dados. O contexto também nos permite ter um controlador que acesse o banco de dados.
Salve as alterações com Ctrl+S.
Adicionar um controlador
Crie uma nova pasta na pasta BlazingPizza . Nomeie-a como Controladores.
Crie um novo arquivo na pasta Controladores . Nomeie-o SpecialsController.cs.
Insira este código para a classe:
using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using BlazingPizza.Data; namespace BlazingPizza.Controllers; [Route("specials")] [ApiController] public class SpecialsController : Controller { private readonly PizzaStoreContext _db; public SpecialsController(PizzaStoreContext db) { _db = db; } [HttpGet] public async Task<ActionResult<List<PizzaSpecial>>> GetSpecials() { return (await _db.Specials.ToListAsync()).OrderByDescending(s => s.BasePrice).ToList(); } }Essa classe cria um controlador que nos permite consultar o banco de dados para ofertas de pizza e os retorna como JSON na URL
(http://localhost:5000/specials).Salve suas alterações.
Carregar dados no banco de dados
O aplicativo verifica se há um banco de dados SQLite existente e cria um com algumas pizzas pré-feitas.
Crie um novo arquivo no diretório De dados . Nomeie-o SeedData.cs.
Insira este código para a classe:
namespace BlazingPizza.Data; public static class SeedData { public static void Initialize(PizzaStoreContext db) { var specials = new PizzaSpecial[] { new PizzaSpecial() { Name = "Basic Cheese Pizza", Description = "It's cheesy and delicious. Why wouldn't you want one?", BasePrice = 9.99m, ImageUrl = "img/pizzas/cheese.jpg", }, new PizzaSpecial() { Id = 2, Name = "The Baconatorizor", Description = "It has EVERY kind of bacon", BasePrice = 11.99m, ImageUrl = "img/pizzas/bacon.jpg", }, new PizzaSpecial() { Id = 3, Name = "Classic pepperoni", Description = "It's the pizza you grew up with, but Blazing hot!", BasePrice = 10.50m, ImageUrl = "img/pizzas/pepperoni.jpg", }, new PizzaSpecial() { Id = 4, Name = "Buffalo chicken", Description = "Spicy chicken, hot sauce and bleu cheese, guaranteed to warm you up", BasePrice = 12.75m, ImageUrl = "img/pizzas/meaty.jpg", }, new PizzaSpecial() { Id = 5, Name = "Mushroom Lovers", Description = "It has mushrooms. Isn't that obvious?", BasePrice = 11.00m, ImageUrl = "img/pizzas/mushroom.jpg", }, new PizzaSpecial() { Id = 7, Name = "Veggie Delight", Description = "It's like salad, but on a pizza", BasePrice = 11.50m, ImageUrl = "img/pizzas/salad.jpg", }, new PizzaSpecial() { Id = 8, Name = "Margherita", Description = "Traditional Italian pizza with tomatoes and basil", BasePrice = 9.99m, ImageUrl = "img/pizzas/margherita.jpg", }, }; db.Specials.AddRange(specials); db.SaveChanges(); } }A classe usa um contexto de banco de dados passado, cria alguns
PizzaSpecialobjetos em uma matriz e os salva.No explorador de arquivos, selecione Program.cs.
Na parte superior, adicione uma referência a um novo
PizzaStoreContext:using BlazingPizza.Data;Essa instrução permite que o aplicativo use o novo serviço.
Insira este segmento acima do
app.Run();método:// Initialize the database var scopeFactory = app.Services.GetRequiredService<IServiceScopeFactory>(); using (var scope = scopeFactory.CreateScope()) { var db = scope.ServiceProvider.GetRequiredService<PizzaStoreContext>(); if (db.Database.EnsureCreated()) { SeedData.Initialize(db); } } app.Run();Essa alteração cria um escopo de banco de dados com o
PizzaStoreContext. Se ainda não houver um banco de dados criado, ele chamará aSeedDataclasse estática para criar um.No momento, o aplicativo não funciona porque o
PizzaStoreContextaplicativo ainda não foi inicializado. No arquivo Program.cs , adicione este código nos serviços atuais (as linhas que iniciambuilder.Services.):builder.Services.AddHttpClient(); builder.Services.AddSqlite<PizzaStoreContext>("Data Source=pizza.db");Esse código registra dois serviços. A primeira
AddHttpClientinstrução permite que o aplicativo acesse comandos HTTP. O aplicativo usa um HttpClient para obter o JSON das ofertas de pizza. A segunda instrução registra o novoPizzaStoreContexte fornece o nome do arquivo para o banco de dados SQLite.
Usar o banco de dados para exibir pizzas
Agora, podemos substituir a pizza codificada na página index.razor.
No explorador de arquivos, expanda Páginas e selecione Index.razor.
Substitua o método existente
OnInitialized()por:protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); }Note
Esse código substitui
OnInitialized()porOnInitializedAsync(). Agora, as especiais retornarão como JSON do aplicativo de forma assíncrona.Há alguns erros que você precisa corrigir. Adicione essas instruções
@injectna diretiva@page:@inject HttpClient HttpClient @inject NavigationManager NavigationManagerSalve todas as alterações e selecione F5 ou Executar. Em seguida, selecione Iniciar Depuração.
Há um erro de runtime ao executar o aplicativo. O JsonReader gerou uma exceção.
Lembre-se de que o aplicativo deve estar criando JSON em
(http://localhost:5000/specials). Vá para essa URL.O aplicativo não sabe como rotear essa solicitação. Você aprende sobre o roteamento no módulo de roteamento do Blazor. Vamos corrigir o erro agora.
Selecione Shift + F5 ou Selecione Parar Depuração.
No explorador de arquivos, selecione Program.cs.
Por volta do meio do arquivo, depois das linhas que iniciam
app., adicione este endpoint:app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");O código agora deve ser:
... app.MapRazorPages(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); ...Selecione F5 ou selecione Executar. Em seguida, selecione Iniciar Depuração.
O aplicativo agora deve funcionar, mas vamos verificar se o JSON está sendo criado corretamente.
Vá para
(http://localhost:5000/specials)para ver:
O JSON tem as pizzas listadas em ordem decrescente de preço, conforme especificado no controlador de pizza especial.