Esercizio - Accedere ai dati da un componente Blazor

Completato

Le pizze predefinite attuali nell'app devono essere sostituite con un database. È possibile usare Microsoft Entity Framework per aggiungere connessioni alle origini dati. In questa app viene usato un database SQLite per archiviare le pizze.

In questo esercizio si aggiungono pacchetti per supportare la funzionalità del database, si connettono classi a un database back-end e si aggiunge una classe helper per precaricare i dati per le pizze dell'azienda.

Aggiungere pacchetti che supportano l'accesso al database

  1. Arrestare l'app se è ancora in esecuzione.

  2. In Visual Studio Code selezionare Terminale>nuovo terminale.

  3. Nel nuovo terminale, imposta la tua posizione nella directory BlazingPizza.

    cd BlazingPizza
    
  4. Eseguire questi comandi per aggiungere i pacchetti Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite e 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
    

    Questi comandi aggiungono riferimenti al pacchetto al file 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>
    

Aggiungere un contesto di database

  1. In Visual Studio Code creare una nuova cartella nella cartella BlazingPizza . Assegnare alla cartella il nome Data.

  2. Nella cartella Dati creare un nuovo file denominato PizzaStoreContext.cs.

  3. Nel nuovo file immettere questo codice per la classe :

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

    Questa classe crea un contesto di database che è possibile usare per registrare un servizio di database. Il contesto consente anche di avere un controller che accede al database.

  4. Salvare le modifiche con CTRL+S.

Aggiungere un controller

  1. Creare una nuova cartella nella cartella BlazingPizza . Assegnare alla cartella il nome Controllers.

  2. Creare un nuovo file nella cartella Controllers . Denominarlo SpecialsController.cs.

  3. Immettere questo codice per la classe :

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

    Questa classe crea un controller che consente di eseguire delle query sul database per ottenere offerte speciali di pizza e restituirli come JSON nell'URL (http://localhost:5000/specials).

  4. Salvare le modifiche.

Caricare i dati nel database

L'app verifica se è presente un database SQLite esistente e ne crea uno con alcune pizze pre-fatte.

  1. Creare un nuovo file nella directory Dati . Denominarlo SeedData.cs.

  2. Immettere questo codice per la classe :

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

    La classe usa un contesto di database passato, crea alcuni PizzaSpecial oggetti in una matrice e li salva.

  3. In Esplora file selezionare Program.cs.

  4. Nella parte superiore aggiungere un riferimento a un nuovo PizzaStoreContextoggetto :

    using BlazingPizza.Data;
    

    Questa istruzione consente all'app di usare il nuovo servizio.

  5. Inserire questo segmento sopra il app.Run(); metodo :

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

    Questa modifica crea un ambito di database con il PizzaStoreContext. Se non è già stato creato un database, chiama la SeedData classe statica per crearne una.

  6. Al momento, l'app non funziona perché PizzaStoreContext non è ancora inizializzata. Nel file Program.cs aggiungere questo codice nei servizi correnti (le righe che iniziano builder.Services.):

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

    Questo codice registra due servizi. La prima AddHttpClient istruzione consente all'app di accedere ai comandi HTTP. L'app usa un httpClient per ottenere il codice JSON per le pizze speciali. La seconda istruzione registra il nuovo PizzaStoreContext e fornisce il nome file per il database SQLite.

Usare il database per visualizzare le pizze

È ora possibile sostituire la pizza specificata a livello di codice nella pagina index.razor.

  1. In Esplora file espandere Pagine e quindi selezionare Index.razor.

  2. Sostituire il metodo esistente OnInitialized() con:

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

    Note

    Questo codice sostituisce OnInitialized() con OnInitializedAsync(). Le offerte speciali ora verranno restituite dall'app come JSON asincronamente.

  3. Ci sono alcuni errori che è necessario correggere. Aggiungere queste istruzioni @inject nella direttiva @page:

    @inject HttpClient HttpClient
    @inject NavigationManager NavigationManager
    
  4. Salvare tutte le modifiche e quindi selezionare F5 o Esegui. Selezionare quindi Avvia debug.

    Si verifica un errore di runtime quando si esegue l'app. JsonReader ha generato un'eccezione.

  5. Tenere presente che l'app deve creare JSON in (http://localhost:5000/specials). Passare a tale URL.

    L'app non sa come instradare questa richiesta. Nel modulo sul routing di Blazor, imparerai il routing. Correggiamo ora l'errore.

  6. Premere MAIUSC + F5 oppure selezionare Arresta debug.

  7. In Esplora file selezionare Program.cs.

  8. Al centro del file, dopo le righe che iniziano app., aggiungere questo endpoint:

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

    Il codice dovrebbe ora essere:

    ...
    app.MapRazorPages();
    app.MapBlazorHub();
    app.MapFallbackToPage("/_Host");
    app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
    ...
    
  9. Selezionare F5 o Esegui. Selezionare quindi Avvia debug.

    L'app dovrebbe funzionare, ma è possibile verificare che il codice JSON sia stato creato correttamente.

  10. Vai a (http://localhost:5000/specials) per vedere:

    Screenshot che mostra il browser con il codice JSON per le pizze.

    Il codice JSON include le pizze elencate in ordine decrescente di prezzo, come specificato nel controller speciale per la pizza.

    Screenshot che mostra ancora più pizze in fiamme.