연습 - 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 폴더에 새 폴더를 만듭니다. 데이터 이름을 지정합니다.
데이터 폴더에서 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 폴더에 새 폴더를 만듭니다. 이름을 'Controllers'로 하세요.
Controllers 폴더에 새 파일을 만듭니다. 이름을 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(); } }이 클래스는 데이터베이스에서 피자 스페셜을 쿼리하고 URL에서 JSON으로 반환할 수 있는 컨트롤러를
(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가 예외를 발생시켰습니다.
앱에서는
(http://localhost:5000/specials)에서 JSON을 생성하고 있어야 합니다. 해당 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에는 특수 피자 컨트롤러에 지정된 대로 내림차순으로 나열된 피자가 있습니다.