Gyakorlat – Adatok kezelése
Az előző gyakorlatban entitásosztályokat és adatbázis-környezetet hozott létre. Ezután EF Core-migrálásokkal hozta létre az adatbázissémát.
Ebben a gyakorlatban végrehajtja a megvalósítást PizzaService
. A szolgáltatás az EF Core használatával hajt végre CRUD-műveleteket az adatbázisban.
A CRUD-műveletek kódolása
A megvalósítás befejezéséhez PizzaService
hajtsa végre a következő lépéseket a Services\PizzaService.cs fájlban:
Végezze el a következő módosításokat a példában látható módon:
- Adjon hozzá egy direktívát
using ContosoPizza.Data;
. - Adjon hozzá egy direktívát
using Microsoft.EntityFrameworkCore;
. - Adjon hozzá egy osztályszintű mezőt a
PizzaContext
konstruktor előtt. - Módosítsa a konstruktormetódus aláírását egy
PizzaContext
paraméter elfogadásához. - Módosítsa a konstruktor metóduskódját a paraméter mezőhöz való hozzárendeléséhez.
using ContosoPizza.Models; using ContosoPizza.Data; using Microsoft.EntityFrameworkCore; namespace ContosoPizza.Services; public class PizzaService { private readonly PizzaContext _context; public PizzaService(PizzaContext context) { _context = context; } /// ... /// CRUD operations removed for brevity /// ... }
A
AddSqlite
Program.cs-hez korábban hozzáadott metódushívás függőséginjektálásra regisztrálvaPizzaContext
. A példány létrehozásakorPizzaContext
aPizzaService
rendszer a konstruktorba injektálja a példányt.- Adjon hozzá egy direktívát
Cserélje le az
GetAll
metódust az alábbi kódra:public IEnumerable<Pizza> GetAll() { return _context.Pizzas .AsNoTracking() .ToList(); }
A fenti kód a következőket végzi el:
- A
Pizzas
gyűjtemény tartalmazza a pizzas tábla összes sorát. - A
AsNoTracking
bővítménymetódus arra utasítja az EF Core-t, hogy tiltsa le a változáskövetést. Mivel ez a művelet írásvédett,AsNoTracking
optimalizálhatja a teljesítményt. - Az összes pizzát a következővel
ToList
küldjük vissza: .
- A
Cserélje le az
GetById
metódust az alábbi kódra:public Pizza? GetById(int id) { return _context.Pizzas .Include(p => p.Toppings) .Include(p => p.Sauce) .AsNoTracking() .SingleOrDefault(p => p.Id == id); }
A fenti kód a következőket végzi el:
- A
Include
bővítménymetódus egy lambda kifejezést használ annak megadásához, hogy a ésSauce
aToppings
navigációs tulajdonságokat a lelkes betöltést használva bele kell foglalni az eredménybe. E kifejezés nélkül az EF Core null értéket ad vissza ezekhez a tulajdonságokhoz. - A
SingleOrDefault
metódus a lambda kifejezésnek megfelelő pizzát ad vissza.- Ha nem egyeznek a rekordok,
null
a rendszer visszaadja. - Ha több rekord egyezik, a rendszer kivételt jelez.
- A lambda kifejezés olyan rekordokat ír le, ahol a
Id
tulajdonság megegyezik aid
paraméterével.
- Ha nem egyeznek a rekordok,
- A
Cserélje le az
Create
metódust az alábbi kódra:public Pizza Create(Pizza newPizza) { _context.Pizzas.Add(newPizza); _context.SaveChanges(); return newPizza; }
A fenti kód a következőket végzi el:
newPizza
a rendszer azt feltételezi, hogy érvényes objektum. Az EF Core nem végez adatérvényesítést, ezért az érvényesítést a ASP.NET Core futtatókörnyezetnek vagy a felhasználói kódnak kell kezelnie.- A
Add
metódus hozzáadja aznewPizza
entitást az EF Core objektumgráfhoz. - A
SaveChanges
metódus arra utasítja az EF Core-t, hogy őrizhesse meg az adatbázis objektummódosításait.
Cserélje le az
UpdateSauce
metódust az alábbi kódra:public void UpdateSauce(int pizzaId, int sauceId) { var pizzaToUpdate = _context.Pizzas.Find(pizzaId); var sauceToUpdate = _context.Sauces.Find(sauceId); if (pizzaToUpdate is null || sauceToUpdate is null) { throw new InvalidOperationException("Pizza or sauce does not exist"); } pizzaToUpdate.Sauce = sauceToUpdate; _context.SaveChanges(); }
A fenti kód a következőket végzi el:
- A meglévőre
Pizza
ésSauce
az objektumokra mutató hivatkozások a használatávalFind
jönnek létre.Find
egy optimalizált módszer a rekordok elsődleges kulcs alapján történő lekérdezésére.Find
először a helyi entitásgráfban keres, mielőtt lekérdezi az adatbázist. - A
Pizza.Sauce
tulajdonság értéke azSauce
objektum. - A
Update
metódushívás szükségtelen, mert az EF Core észleli, hogy a tulajdonságot aSauce
következőrePizza
állította be: . - A
SaveChanges
metódus arra utasítja az EF Core-t, hogy őrizhesse meg az adatbázis objektummódosításait.
- A meglévőre
Cserélje le az
AddTopping
metódust az alábbi kódra:public void AddTopping(int pizzaId, int toppingId) { var pizzaToUpdate = _context.Pizzas.Find(pizzaId); var toppingToAdd = _context.Toppings.Find(toppingId); if (pizzaToUpdate is null || toppingToAdd is null) { throw new InvalidOperationException("Pizza or topping does not exist"); } if(pizzaToUpdate.Toppings is null) { pizzaToUpdate.Toppings = new List<Topping>(); } pizzaToUpdate.Toppings.Add(toppingToAdd); _context.SaveChanges(); }
A fenti kód a következőket végzi el:
- A meglévőre
Pizza
ésTopping
az objektumokra mutató hivatkozások a használatávalFind
jönnek létre. - Az
Topping
objektum a metódussal lesz hozzáadva aPizza.Toppings
gyűjteményhez.Add
. Új gyűjtemény jön létre, ha nem létezik. - A
SaveChanges
metódus arra utasítja az EF Core-t, hogy őrizhesse meg az adatbázis objektummódosításait.
- A meglévőre
Cserélje le az
DeleteById
metódust az alábbi kódra:public void DeleteById(int id) { var pizzaToDelete = _context.Pizzas.Find(id); if (pizzaToDelete is not null) { _context.Pizzas.Remove(pizzaToDelete); _context.SaveChanges(); } }
A fenti kód a következőket végzi el:
- A
Find
metódus lekéri a pizzát az elsődleges kulccsal (ebben azId
esetben). - A
Remove
metódus eltávolítja az entitást azpizzaToDelete
EF Core objektumgráfjában. - A
SaveChanges
metódus arra utasítja az EF Core-t, hogy őrizhesse meg az adatbázis objektummódosításait.
- A
Mentse az összes módosítást, és futtassa a parancsot
dotnet build
. Javítsa ki az esetleges hibákat.
Az adatbázis üzembe helyezése
Kódoltuk a CRUD-műveleteket a számára PizzaService
, de könnyebb tesztelni az olvasási műveletet, ha az adatbázis jó adatokat tartalmaz. Úgy dönt, hogy úgy módosítja az alkalmazást, hogy elindítsa az adatbázist.
Figyelmeztetés
Ez az adatbázis-vetési kód nem veszi figyelembe a versenyfeltételeket, ezért legyen óvatos, ha elosztott környezetben használja a módosítások enyhítése nélkül.
Az Adatok mappában adjon hozzá egy dbInitializer.cs nevű új fájlt.
Adja hozzá a következő kódot a Data\DbInitializer.cs fájlhoz:
using ContosoPizza.Models; namespace ContosoPizza.Data { public static class DbInitializer { public static void Initialize(PizzaContext context) { if (context.Pizzas.Any() && context.Toppings.Any() && context.Sauces.Any()) { return; // DB has been seeded } var pepperoniTopping = new Topping { Name = "Pepperoni", Calories = 130 }; var sausageTopping = new Topping { Name = "Sausage", Calories = 100 }; var hamTopping = new Topping { Name = "Ham", Calories = 70 }; var chickenTopping = new Topping { Name = "Chicken", Calories = 50 }; var pineappleTopping = new Topping { Name = "Pineapple", Calories = 75 }; var tomatoSauce = new Sauce { Name = "Tomato", IsVegan = true }; var alfredoSauce = new Sauce { Name = "Alfredo", IsVegan = false }; var pizzas = new Pizza[] { new Pizza { Name = "Meat Lovers", Sauce = tomatoSauce, Toppings = new List<Topping> { pepperoniTopping, sausageTopping, hamTopping, chickenTopping } }, new Pizza { Name = "Hawaiian", Sauce = tomatoSauce, Toppings = new List<Topping> { pineappleTopping, hamTopping } }, new Pizza { Name="Alfredo Chicken", Sauce = alfredoSauce, Toppings = new List<Topping> { chickenTopping } } }; context.Pizzas.AddRange(pizzas); context.SaveChanges(); } } }
A fenti kód a következőket végzi el:
- Az
DbInitializer
osztály és aInitialize
metódus is a következőként van definiálva:static
. Initialize
paraméterként fogad el egyPizzaContext
objektumot.- Ha a három tábla egyikében sem található rekord,
Pizza
a ,Sauce
ésTopping
az objektumok létrejönnek. - Az
Pizza
objektumok (és azokSauce
Topping
navigációs tulajdonságai) az objektumgráfhoz a használatával lesznek hozzáadvaAddRange
. - Az objektumgráf módosításait a használatával véglegesíteni kell az adatbázis számára
SaveChanges
.
- Az
Az DbInitializer
osztály készen áll az adatbázis magvetésére, de a Program.cs fájlból kell meghívni. A következő lépések létrehoznak egy bővítménymetódust a hívásokhoz IHost
DbInitializer.Initialize
:
Az Adatok mappában adjon hozzá egy Extensions.cs nevű új fájlt.
Adja hozzá a következő kódot a Data\Extensions.cs fájlhoz:
namespace ContosoPizza.Data; public static class Extensions { public static void CreateDbIfNotExists(this IHost host) { { using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService<PizzaContext>(); context.Database.EnsureCreated(); DbInitializer.Initialize(context); } } } }
A fenti kód a következőket végzi el:
A
CreateDbIfNotExists
metódus a bővítményekéntIHost
van definiálva.Létrejön egy hivatkozás a
PizzaContext
szolgáltatásra.Győződjön meg arról, hogy a Létrehozás biztosítja , hogy az adatbázis létezik.
Fontos
Ha nem létezik adatbázis,
EnsureCreated
hozzon létre egy új adatbázist. Az új adatbázis nincs migrálásra konfigurálva, ezért óvatosan használja ezt a módszert.A
DbIntializer.Initialize
metódus neve. AzPizzaContext
objektum paraméterként lesz átadva.
Végül a Program.cs fájlban cserélje le a
// Add the CreateDbIfNotExists method call
megjegyzést a következő kódra az új bővítménymetódus meghívásához:app.CreateDbIfNotExists();
Ez a kód meghívja a korábban definiált bővítménymetódust az alkalmazás minden futtatásakor.
Mentse az összes módosítást, és futtassa a parancsot
dotnet build
.
Megírta az alapszintű CRUD-műveletek végrehajtásához szükséges összes kódot, és elindítja az adatbázist. A következő gyakorlatban ezeket a műveleteket teszteli az alkalmazásban.