練習 - 從 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 6.0.8 dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 6.0.8 dotnet add package System.Net.Http.Json --version 6.0.0
這些命令會將套件參考新增至 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>
新增資料庫內容
在 Visual Studio Code 中,於 BlazingPizza 資料夾內建立新的資料夾。 將其命名為 Data。
在 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; } }
此類別會建立可用來註冊資料庫服務的資料庫內容。 此內容也可讓我們具有可存取資料庫的控制器。
儲存您的變更。
新增控制器
在 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(); } }
此類別會建立控制器,讓我們查詢資料庫是否有特製披薩,並在
(http://localhost:5000/specials)
URL 以 JSON 形式傳回。儲存您的變更。
將資料載入資料庫
應用程式會查看是否有現有的 SQLite 資料庫,並使用一些預先製作的披薩來建立一個資料庫。
在 Data 目錄中建立新的檔案。 將其命名為 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 檔案中較高位置的Add Services to the container
區段中,於目前的服務 (啟動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"); }
注意
此程式碼已將
OnInitialized()
取代為OnInitializedAsync()
。 特製披薩現在會以非同步方式從應用程式傳回為 JSON。有一些您需要修正的錯誤。 在
@page
指示詞下新增這些@inject
陳述式:@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 會依特殊披薩控制器中指定的價格遞減列出披薩。