練習 - 從 Blazor 元件存取數據

已完成

應用程式中目前的硬式編碼披薩必須以資料庫取代。 您可以使用 Microsoft Entity Framework,將連線新增至數據源。 在此應用程式中,我們使用 SQLite 資料庫來儲存披薩。

在此練習中,您會新增套件以支持資料庫功能、將類別連線到後端資料庫,以及新增協助程序類別來預先載入公司的披薩數據。

新增支援數據庫存取的套件

  1. 如果應用程式仍在執行中,請停止該應用程式。

  2. 在 Visual Studio Code 中,選取 終端機>新增終端機

  3. 在新終端機中,將您的位置設定為 BlazingPizza 目錄。

    cd BlazingPizza
    
  4. 執行下列命令以新增 Microsoft.EntityFrameworkCoreMicrosoft.EntityFrameworkCore.SqliteSystem.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>
    

新增資料庫上下文

  1. 在 Visual Studio Code 中,在 BlazingPizza 資料夾中建立新的資料夾。 將它命名為 Data

  2. [數據] 資料夾中,建立名為 PizzaStoreContext.cs 的新檔案。

  3. 在新檔案中,輸入 類別的這個程式代碼:

    using Microsoft.EntityFrameworkCore;
    
    namespace BlazingPizza.Data;
    
    public class PizzaStoreContext : DbContext
    {
        public PizzaStoreContext(DbContextOptions options) : base(options)
        {
        }
    
        public DbSet<PizzaSpecial> Specials { get; set; }
    }    
    

    這個類別會建立可用來註冊資料庫服務的資料庫內容。 內容也允許我們有可存取資料庫的控制器。

  4. 使用 Ctrl+S 儲存變更。

新增控制器

  1. BlazingPizza 資料夾中建立新的資料夾。 將它命名為 Controllers

  2. Controllers 資料夾中建立新的檔案。 將它命名 為SpecialsController.cs

  3. 輸入 類別的這個程式代碼:

    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 形式傳回至 (http://localhost:5000/specials) URL。

  4. 儲存您的變更。

將數據載入資料庫

應用程式會查看是否有現有的 SQLite 資料庫,並使用一些預先製作的披薩來建立一個資料庫。

  1. 資料 目錄中建立新的檔案。 將它命名 為SeedData.cs

  2. 輸入 類別的這個程式代碼:

    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 物件,然後儲存。

  3. 在檔案總管中,選取 [Program.cs]。

  4. 在頂端,將參考新增至新的 PizzaStoreContext

    using BlazingPizza.Data;
    

    此語句可讓應用程式使用新的服務。

  5. 將此區段插入至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 靜態類別來建立一個資料庫。

  6. 目前,應用程式無法運作,因為 PizzaStoreContext 尚未初始化 。 在 Program.cs 檔案中,在目前的服務底下新增此程式代碼(開始 builder.Services.的行):

      builder.Services.AddHttpClient();
      builder.Services.AddSqlite<PizzaStoreContext>("Data Source=pizza.db");
    
    

    此程式代碼會註冊兩個服務。 第一個 AddHttpClient 語句可讓應用程式存取 HTTP 命令。 應用程式會使用 HttpClient 來取得披薩特價的 JSON。 第二個語句會註冊新的 PizzaStoreContext ,並提供 SQLite 資料庫的檔名。

使用資料庫來顯示披薩

我們現在可以在 Index.razor 頁面中取代硬式編碼的披薩。

  1. 在檔案總管中,展開 [頁面],然後選取 [Index.razor]。

  2. 將現有的 OnInitialized() 方法取代為:

    protected override async Task OnInitializedAsync()
    {
        specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials");
    }
    

    Note

    此程式代碼會 OnInitialized() 取代為 OnInitializedAsync()。 特製披薩現在會以非同步方式從應用程式傳回為 JSON。

  3. 您需要修正一些錯誤。 在 @inject 指示詞底下新增這些@page語句:

    @inject HttpClient HttpClient
    @inject NavigationManager NavigationManager
    
  4. 儲存所有變更,然後選取 F5 或選取 [ 執行]。 然後選取 [開始偵錯]。

    當您執行應用程式時發生運行時錯誤。 JsonReader 引發例外狀況。

  5. 請記住,應用程式應該在 (http://localhost:5000/specials) 建立 JSON。 移至該 URL。

    應用程式不知道如何路由傳送此要求。 您要在 Blazor 路由課程模組中了解路由。 現在讓我們修正錯誤。

  6. 選取 Shift + F5,或選取 [停止偵錯]。

  7. 在檔案總管中,選取 [Program.cs]。

  8. 在檔案中間,在開始 app.的行之後,新增此端點:

    app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    

    程式代碼現在應該是:

    ...
    app.MapRazorPages();
    app.MapBlazorHub();
    app.MapFallbackToPage("/_Host");
    app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    ...
    
  9. 選取 F5 或選取 [ 執行]。 然後選取 [開始偵錯]。

    應用程式現在應該可以運作,但讓我們檢查 JSON 是否已正確建立。

  10. 移動到(http://localhost:5000/specials)以查看:

    顯示瀏覽器的螢幕擷取畫面,其顯示披薩的 JSON。

    JSON 會依照特殊披薩控制器中指定的價格遞減順序列出披薩。

    顯示更多燃燒披薩的螢幕快照。