Exercício - Acessar dados de um componente Blazor
As pizzas codificadas atuais 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, adicionam-se pacotes para suportar a funcionalidade de base de dados, conectam-se classes a uma base de dados de back-end e adiciona-se uma classe auxiliar para pré-carregar dados para as pizzas da empresa.
Adicionar pacotes que suportam acesso ao banco de dados
Pare o aplicativo se ele ainda estiver em execução.
Em Visual Studio Code, selecione Terminal>Novo Terminal.
No novo terminal, defina a 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.0Estes comandos adicionam referências de pacote ao seu 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. Atribua o nome Data.
Na pasta Dados , crie um novo arquivo chamado PizzaStoreContext.cs.
No novo ficheiro, introduza 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 acede à base de dados.
Salve suas alterações com Ctrl+S.
Adicionar um controlador
Crie uma nova pasta na pasta BlazingPizza. Nomeie-o Controladores.
Crie um novo ficheiro na pasta Controllers. 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 a base de dados para pizzas especiais e retorná-las como JSON no 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é-fabricadas.
Crie um novo arquivo no diretório Data. Dê o nome de 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
PizzaSpecialem uma matriz e, em seguida, os salva.No explorador de ficheiros, selecione Program.cs.
Na parte superior, adicione uma referência a um novo
PizzaStoreContext:using BlazingPizza.Data;Esta declaraçã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 de banco de dados com o
PizzaStoreContext. Se não houver um banco de dados já criado, ele chamará a classe estáticaSeedDatapara criar um.No momento, o aplicativo não funciona porque o
PizzaStoreContextainda não foi inicializado. No arquivo Program.cs , adicione este código sob os serviços atuais (as linhas que iniciambuilder.Services.):builder.Services.AddHttpClient(); builder.Services.AddSqlite<PizzaStoreContext>("Data Source=pizza.db");Este código regista dois serviços. A primeira instrução
AddHttpClientpermite que o aplicativo acesse comandos HTTP. A aplicação usa um HttpClient para obter o JSON para promoções de pizza. A segunda instrução registra o novoPizzaStoreContexte fornece o nome do arquivo para o banco de dados SQLite.
Use o banco de dados para exibir pizzas
Agora podemos substituir a pizza codificada na página Index.razor.
No explorador de ficheiros, expanda Páginas e, em seguida, selecione Index.razor.
Substitua o método
OnInitialized()existente por:protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); }Note
Este código substitui
OnInitialized()porOnInitializedAsync(). Os especiais agora serão devolvidos como JSON da aplicação de forma assíncrona.Há alguns erros que você precisa corrigir. Aditar estas
@injectdeclarações na diretiva@page:@inject HttpClient HttpClient @inject NavigationManager NavigationManagerSalve todas as alterações e selecione F5 ou selecione Executar. Em seguida, selecione Iniciar a depuração.
Há um erro de tempo de execução quando você executa o aplicativo. O JsonReader levantou uma exceção.
Lembre-se de que o aplicativo deve criar JSON em
(http://localhost:5000/specials). Vá para esse URL.O aplicativo não sabe como rotear essa solicitação. Você aprende sobre como funciona o roteamento no módulo de roteamento do Blazor. Vamos corrigir o erro agora.
Selecione Shift + F5ou selecione Parar a Depuração.
No explorador de ficheiros, selecione Program.cs.
No meio do arquivo, após as linhas que iniciam
app., adicione este endpoint:app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");O código deve agora 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 a depuração.
O aplicativo agora deve funcionar, mas vamos verificar se o JSON está sendo criado corretamente.
Vá até
(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.