Упражнение. Доступ к данным из компонента Blazor
Текущие жестко закодированные пиццы в приложении должны быть заменены базой данных. Microsoft Entity Framework можно использовать для добавления подключений к источникам данных. В этом приложении мы используем базу данных SQLite для хранения пиццы.
В этом упражнении вы добавите пакеты для поддержки функций базы данных, подключите классы к серверной базе данных и добавьте вспомогательный класс для предварительной загрузки данных для пиццы компании.
Добавление пакетов, поддерживающих доступ к базе данных
Остановите приложение, если оно по-прежнему запущено.
В Visual Studio Code выберите терминал>"Новый терминал".
В новом терминале задайте расположение в каталоге BlazingPizza.
cd BlazingPizzaВыполните следующие команды, чтобы добавить пакеты Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite и 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.0Эти команды добавляют ссылки на пакеты в файл 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>
Добавление контекста базы данных
В Visual Studio Code создайте новую папку в папке BlazingPizza . Назовите его data.
В папке "Данные" создайте файл с именем PizzaStoreContext.cs.
В новом файле введите этот код для класса:
using Microsoft.EntityFrameworkCore; namespace BlazingPizza.Data; public class PizzaStoreContext : DbContext { public PizzaStoreContext(DbContextOptions options) : base(options) { } public DbSet<PizzaSpecial> Specials { get; set; } }Этот класс создает контекст базы данных, который можно использовать для регистрации службы базы данных. Контекст также позволяет нам иметь контроллер, который обращается к базе данных.
Сохраните изменения, нажав клавиши CTRL+S.
Добавление контроллера
Создайте новую папку в папке BlazingPizza . Назовите это контроллеры.
Создайте новый файл в папке контроллеров . Назовите его SpecialsController.cs.
Введите этот код для класса:
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(); } }Этот класс создает контроллер, позволяющий запрашивать базу данных для специальных элементов пиццы и возвращать их в виде JSON по URL-адресу
(http://localhost:5000/specials).Сохраните изменения.
Загрузка данных в базу данных
Приложение проверяет наличие существующей базы данных SQLite и, если её нет, создаёт новую с заранее подготовленными пиццами.
Создайте новый файл в каталоге данных. Назовите его SeedData.cs.
Введите этот код для класса:
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(); } }Класс использует переданный контекст базы данных, создает некоторые объекты
PizzaSpecialв массиве, а затем сохраняет их.В проводнике выберите Program.cs.
Вверху добавьте ссылку на новую
PizzaStoreContext:using BlazingPizza.Data;Эта инструкция позволяет приложению использовать новую службу.
Вставьте этот сегмент над методом
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();Это изменение создаёт область в базе данных с
PizzaStoreContext. Если база данных еще не создана, она вызываетSeedDataстатический класс для создания.На данный момент приложение не работает, так как
PizzaStoreContextеще не инициализирован. В файле Program.cs добавьте этот код в текущие службы (строки, начинающиесяbuilder.Services.):builder.Services.AddHttpClient(); builder.Services.AddSqlite<PizzaStoreContext>("Data Source=pizza.db");Этот код регистрирует две службы. Первая инструкция
AddHttpClientпозволяет приложению получать доступ к командам HTTP. Приложение использует HttpClient для получения JSON для специальных предложений по пицце. Вторая инструкция регистрирует новыйPizzaStoreContextи предоставляет имя файла для базы данных SQLite.
Использование базы данных для отображения пицц
Теперь можно заменить жестко закодированную пиццу на странице Index.razor.
В проводнике разверните страницы и выберите Index.razor.
Замените существующий метод
OnInitialized()следующим:protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); }Note
Этот код заменяет
OnInitialized()наOnInitializedAsync(). Специальные компоненты теперь будут возвращены в формате JSON из приложения асинхронно.Существуют некоторые ошибки, которые необходимо исправить. Добавьте эти инструкции
@injectв директиву@page:@inject HttpClient HttpClient @inject NavigationManager NavigationManagerСохраните все изменения, а затем выберите F5 или Запустить. Затем выберите начать отладку.
При запуске приложения возникает ошибка среды выполнения. JsonReader вызвал исключение.
Помните, что приложение должно создавать JSON в
(http://localhost:5000/specials). Перейдите по url-адресу.Приложение не знает, как маршрутизировать этот запрос. Вы узнаете о маршрутизации в модуле Blazor, посвященном этому вопросу. Давайте исправим ошибку сейчас.
Выберите SHIFT + F5 или нажмите кнопку "Остановить отладку".
В проводнике выберите Program.cs.
В середине файла после строк, начинающихся
app., добавьте следующую конечную точку:app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");Теперь код должен быть следующим:
... app.MapRazorPages(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); ...Выберите F5 или выберите Запустить. Затем выберите начать отладку.
Теперь приложение должно работать, но давайте проверим правильность создания JSON.
Перейдите к
(http://localhost:5000/specials), чтобы увидеть:
JSON содержит список пицц в порядке убывания цены, как указано в специальном контроллере пиццы.