Övning – Få åtkomst till data från en Blazor-komponent

Slutförd

De nuvarande hårdkodade pizzorna i appen måste ersättas med en databas. Du kan använda Microsoft Entity Framework för att lägga till anslutningar till datakällor. I den här appen använder vi en SQLite-databas för att lagra pizzan.

I den här övningen lägger du till paket som stöder databasfunktioner, ansluter klasser till en serverdelsdatabas och lägger till en hjälpklass för att förinläsa data för företagets pizzor.

Lägga till paket som stöder databasåtkomst

  1. Stoppa appen om den fortfarande körs.

  2. I Visual Studio Code väljer du Terminal>New Terminal.

  3. I den nya terminalen anger du platsen till katalogen BlazingPizza.

    cd BlazingPizza
    
  4. Kör dessa kommandon för att lägga till paketen Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite och 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
    

    Dessa kommandon lägger till paketreferenser till filen 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>
    

Lägga till en databaskontext

  1. I Visual Studio Code skapar du en ny mapp i mappen BlazingPizza. Ge den namnet Data.

  2. I mappen Data skapar du en ny fil med namnet PizzaStoreContext.cs.

  3. I den nya filen anger du den här koden för klassen:

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

    Den här klassen skapar en databaskontext som vi kan använda för att registrera en databastjänst. Med kontexten kan vi också ha en kontrollant som har åtkomst till databasen.

  4. Spara ändringarna med Ctrl+S.

Lägga till en kontrollant

  1. Skapa en ny mapp i mappen BlazingPizza. Ge den namnet Kontroller.

  2. Skapa en ny fil i mappen Controllers. Ge den namnet SpecialsController.cs.

  3. Ange den här koden för klassen:

    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();
        }
    }
    

    Den här klassen skapar en kontrollant som gör att vi kan fråga databasen efter pizzaspecialer och returnerar dem som JSON på (http://localhost:5000/specials)-URL:en.

  4. Spara ändringarna.

Läsa in data i databasen

Appen kontrollerar om det finns en befintlig SQLite-databas och skapar en med några färdiga pizzor.

  1. Skapa en ny fil i katalogen Data. Ge den namnet SeedData.cs.

  2. Ange den här koden för klassen:

    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();
        }
    }
    

    Klassen använder en godkänd databaskontext, skapar vissa PizzaSpecial objekt i en matris och sparar dem sedan.

  3. I utforskaren väljer du Program.cs.

  4. Överst lägger du till en referens till en ny PizzaStoreContext:

    using BlazingPizza.Data;
    

    Med den här instruktionen kan appen använda den nya tjänsten.

  5. Infoga det här segmentet ovanför metoden 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();
    

    Den här ändringen skapar ett databasomfång med PizzaStoreContext. Om det inte redan finns en databas som har skapats anropas den SeedData statiska klassen för att skapa en.

  6. För närvarande fungerar inte appen eftersom den PizzaStoreContext inte har initierats ännu. I filen Program.cs lägger du till den här koden under de aktuella tjänsterna (raderna som startar builder.Services.):

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

    Den här koden registrerar två tjänster. Med den första AddHttpClient-instruktionen kan appen komma åt HTTP-kommandon. Appen använder en HttpClient för att hämta JSON för pizzaspecialer. Den andra instruktionen registrerar den nya PizzaStoreContext och tillhandahåller filnamnet för SQLite-databasen.

Använd databasen för att visa pizzor

Nu kan vi ersätta den hårdkodade pizzan i Index.razor-sidan.

  1. I utforskaren expanderar du Sidor och väljer sedan Index.razor.

  2. Ersätt den befintliga metoden OnInitialized() med:

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

    Note

    Den här koden ersätter OnInitialized() med OnInitializedAsync(). Specialerbjudanden kommer nu att returneras som JSON från appen asynkront.

  3. Det finns några fel som du behöver åtgärda. Lägg till dessa @inject-instruktioner under @page-direktivet:

    @inject HttpClient HttpClient
    @inject NavigationManager NavigationManager
    
  4. Spara alla ändringar och välj sedan F5 eller välj Kör. Välj sedan Starta felsökning.

    Det uppstår ett körningsfel när du kör appen. JsonReader utlöste ett undantag.

  5. Kom ihåg att appen bör skapa JSON på (http://localhost:5000/specials). Gå till den URL:en.

    Appen vet inte hur den här begäran ska dirigeras. Du lär dig mer om routning i modulen på Blazor-routning. Nu ska vi åtgärda felet.

  6. Välj Skift + F5eller välj Sluta felsöka.

  7. I utforskaren väljer du Program.cs.

  8. Lägg till den här slutpunkten runt mitten av filen efter raderna som börjar app.:

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

    Koden bör nu vara:

    ...
    app.MapRazorPages();
    app.MapBlazorHub();
    app.MapFallbackToPage("/_Host");
    app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    ...
    
  9. Välj F5 eller välj Kör. Välj sedan Starta felsökning.

    Appen bör nu fungera, men låt oss kontrollera att JSON skapas korrekt.

  10. Gå till (http://localhost:5000/specials) för att se:

    Skärmbild som visar webbläsaren som visar JSON för pizzor.

    JSON har pizzorna listade i fallande prisordning enligt vad som anges i den speciella pizzastyrenheten.

    Skärmbild som visar ännu mer flammande pizzor.