Exercício: acessar dados de um componente Blazor
As pizzas atuais codificadas 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, usaremos um banco de dados SQLite para armazenar as pizzas.
Nesse exercício, você adicionará pacotes para dar suporte à funcionalidade do banco de dados, conectará nossas classes a um banco de dados de back-end e adicionará uma classe auxiliar para pré-carregar dados das pizzas da empresa.
Adicionar pacotes para dar 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 BlazingPizza
Execute estes comandos para adicionar os pacotes Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite e System.Net.Http.Json:
dotnet add package Microsoft.EntityFrameworkCore --version 6.0.8 dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 6.0.8 dotnet add package System.Net.Http.Json --version 6.0.0
Estes comandos adicionam referências de pacote ao arquivo BlazingPizza.csproj:
<ItemGroup> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.8" /> <PackageReference Include="System.Net.Http.Json" Version="6.0.0" /> </ItemGroup>
Adicionar um contexto de banco de dados
No Visual Studio Code, crie uma nova pasta em BlazingPizza. Nomeie-a Dados.
Crie um arquivo dentro da pasta de Dados. Nomeie-o como PizzaStoreContext.cs.
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 acessa o banco de dados.
Salve suas alterações.
Adicionar um controlador
Crie uma nova pasta BlazingPizza. Nomeie-a como Controladores.
Crie um novo arquivo na pasta Controladores. Nomeie-o como 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 permite consultar o banco de dados em busca de pizzas especiais e retorná-las 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é-preparadas.
Crie um novo arquivo no diretório de Dados. Nomeie-o como 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 objetos
PizzaSpecial
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 método
app.Run();
:... // 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 do banco de dados com o
PizzaStoreContext
. Se não houver um banco de dados já criado, ele chamará a classe estáticaSeedData
para criar um.No momento, o aplicativo não funciona porque não inicializamos o
PizzaStoreContext
. Na seção superiorAdd Services to the container
do 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 instrução
AddHttpClient
permite que o aplicativo acesse comandos HTTP. O aplicativo usa um HttpClient para obter o JSON para pizzas especiais. A segunda instrução registra o novoPizzaStoreContext
e 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, selecione Index.razor.
Substitua o método
OnInitialized()
existente por:protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); }
Observação
Esse código substituiu
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
@inject
na diretiva@page
:@inject HttpClient HttpClient @inject NavigationManager NavigationManager
Salve todas as alterações e selecione F5 ou Executar. Selecione Iniciar Depuração.
Ocorre um erro de runtime ao executar o aplicativo. O JsonReader gerou uma exceção.
Lembre-se de que o aplicativo deve criar o JSON em
(http://localhost:5000/specials)
. Vá para essa URL.O aplicativo não sabe como rotear essa solicitação. Você aprenderá sobre roteamento no módulo sobre roteamento do Blazor. Vamos corrigir o erro.
Selecione Shift + F5 ou selecione Parar Depuração.
No explorador de arquivos, selecione Program.cs.
No meio do arquivo, após as linhas iniciadas
app.
, adicione este ponto de extremidade:app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
Agora, o código deve ser:
... app.MapRazorPages(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); ...
Selecione F5 ou Executar. Selecione Iniciar Depuração.
O aplicativo deve funcionar, mas vamos verificar se o JSON está sendo criado corretamente.
Vá para
(http://localhost:5000/specials)
para ver:O JSON lista as pizzas em ordem decrescente de preço, conforme especificado no controlador de pizza especial.