Übung: Zugreifen auf Daten über eine Blazor-Komponente
Die derzeit hartcodierten Pizzas in der App müssen durch eine Datenbank ersetzt werden. Sie können Microsoft Entity Framework verwenden, um Verbindungen zu Datenquellen hinzuzufügen. In dieser App wird eine SQLite-Datenbank zum Speichern der Pizzen verwendet.
In dieser Übung fügen Sie Pakete hinzu, um die Datenbankfunktionen zu unterstützen, verbinden die Klassen mit einer Back-End-Datenbank und fügen eine Hilfsklasse hinzu, um Daten für die Pizzen des Unternehmens vorab zu laden.
Hinzufügen von Paketen zur Unterstützung des Datenbankzugriffs
Halten Sie die App an, falls diese noch ausgeführt wird.
Wählen Sie in Visual Studio Code Terminal>NeuesTerminal aus.
Legen Sie im neuen Terminal den Speicherort auf das Verzeichnis BlazingPizza fest.
cd BlazingPizza
Führen Sie die folgenden Befehle aus, um die Pakete Microsoft.EntityFrameworkCore, Microsoft.EntityFrameworkCore.Sqlite und System.Net.Http.Json hinzuzufügen:
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
Diese Befehle fügen Ihrer BlazingPizza.csproj-Datei Paketverweise hinzu:
<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>
Hinzufügen eines Datenbankkontexts
Erstellen Sie in Visual Studio Code im Ordner BlazingPizza einen neuen Ordner. Nennen Sie ihn Data.
Erstellen Sie im Ordner Data eine neue Datei. Nennen Sie sie PizzaStoreContext.cs.
Geben Sie diesen Code für die Klasse ein:
using Microsoft.EntityFrameworkCore; namespace BlazingPizza.Data; public class PizzaStoreContext : DbContext { public PizzaStoreContext(DbContextOptions options) : base(options) { } public DbSet<PizzaSpecial> Specials { get; set; } }
Diese Klasse erstellt einen Datenbankkontext, der zum Registrieren eines Datenbankdiensts verwendet werden kann. Der Kontext ermöglicht uns außerdem, einen Controller zu verwenden, der auf die Datenbank zugreift.
Speichern Sie die Änderungen.
Hinzufügen eines Controllers
Erstellen Sie im Ordner BlazingPizza einen neuen Ordner. Nennen Sie ihn Controllers.
Erstellen Sie im Ordner Controllers eine neue Datei. Nennen Sie sie SpecialsController.cs.
Geben Sie diesen Code für die Klasse ein:
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(); } }
Diese Klasse erstellt einen Controller, mit dem die Datenbank nach Pizzaspezialitäten abgefragt werden kann, die dann als JSON-Code an die URL
(http://localhost:5000/specials)
zurückgegeben werden.Speichern Sie die Änderungen.
Laden von Daten in die Datenbank
Die App überprüft, ob eine SQLite-Datenbank vorhanden ist, und erstellt eine mit einigen vorgefertigten Pizzen.
Erstellen Sie im Verzeichnis Data eine neue Datei. Nennen Sie sie SeedData.cs.
Geben Sie diesen Code für die Klasse ein:
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(); } }
Die Klasse verwendet einen übergebenen Datenbankkontext, erstellt einige
PizzaSpecial
-Objekte in einem Array und speichert diese dann.Wählen Sie im Datei-Explorer die Datei Program.cs aus.
Fügen Sie ganz oben einen Verweis auf einen neuen
PizzaStoreContext
hinzu:using BlazingPizza.Data;
Mit dieser Anweisung kann die App den neuen Dienst verwenden.
Fügen Sie dieses Segment über der
app.Run();
-Methode ein:... // 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();
Durch diese Änderung wird ein Datenbankbereich mit dem
PizzaStoreContext
erstellt. Wenn noch keine Datenbank erstellt wurde, wird die statische KlasseSeedData
aufgerufen, um eine zu erstellen.Zurzeit funktioniert die App nicht, da der
PizzaStoreContext
nicht initialisiert wurde. Fügen Sie im AbschnittAdd Services to the container
weiter oben in der Datei Program.cs diesen Code unter den aktuellen Diensten (die mitbuilder.Services.
beginnenden Zeilen) ein:builder.Services.AddHttpClient(); builder.Services.AddSqlite<PizzaStoreContext>("Data Source=pizza.db");
Dieser Code registriert zwei Dienste. Die erste
AddHttpClient
-Anweisung ermöglicht der App den Zugriff auf HTTP-Befehle. Die App verwendet einen HttpClient, um den JSON-Code für besondere Pizza-Angebote abzurufen. Die zweite Anweisung registriert den neuenPizzaStoreContext
und stellt den Dateinamen für die SQLite-Datenbank zur Verfügung.
Verwenden der Datenbank zum Anzeigen von Pizzas
Jetzt kann die hartcodierte Pizza auf der Seite Index.razor ersetzt werden.
Wählen Sie im Datei-Explorer Index.razor aus.
Ersetzen Sie die vorhandene
OnInitialized()
-Methode durch Folgendes:protected override async Task OnInitializedAsync() { specials = await HttpClient.GetFromJsonAsync<List<PizzaSpecial>>(NavigationManager.BaseUri + "specials"); }
Hinweis
Dieser Code hat
OnInitialized()
durchOnInitializedAsync()
ersetzt. Spezialitäten werden jetzt asynchron als JSON-Code von der App zurückgegeben.Es gibt einige Fehler, die Sie beheben müssen. Fügen Sie diese
@inject
-Anweisungen unter der@page
-Anweisung hinzu:@inject HttpClient HttpClient @inject NavigationManager NavigationManager
Speichern Sie alle Änderungen, und drücken Sie dann F5, oder wählen Sie Ausführen aus. Wählen Sie dann Debuggen starten aus.
Beim Ausführen der App tritt ein Laufzeitfehler auf. JsonReader hat eine Ausnahme ausgelöst.
Denken Sie daran, dass die App JSON-Code unter
(http://localhost:5000/specials)
erstellen sollte. Wechseln Sie zu der betreffenden URL.Die App weiß nicht, wie diese Anforderung weitergeleitet werden soll. Informationen zum Routing finden Sie im Modul zum Blazor-Routing. Nun beheben Sie den Fehler.
Drücken Sie UMSCHALTTASTE + F5, oder wählen Sie Debuggen beenden aus.
Wählen Sie im Datei-Explorer die Datei Program.cs aus.
Fügen Sie in der Mitte der Datei nach den Zeilen, die mit
app.
beginnen, diesen Endpunkt hinzu:app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
Der Code sollte nun wie folgt lauten:
... app.MapRazorPages(); app.MapBlazorHub(); app.MapFallbackToPage("/_Host"); app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}"); ...
Wählen Sie F5 oder Ausführen aus. Wählen Sie dann Debuggen starten aus.
Die App sollte jetzt funktionieren, doch überprüfen Sie, ob der JSON-Code ordnungsgemäß erstellt wird.
Wechseln Sie zu
(http://localhost:5000/specials)
, um dies anzuzeigen:Im JSON-Code sind die Pizzen nach Preis in absteigender Reihenfolge aufgelistet, wie es im Controller für die Sonderpizzen angegeben ist.