Gyakorlat – Adatok kezelése

Befejeződött

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:

  1. Végezze el a következő módosításokat a példában látható módon:

    1. Adjon hozzá egy direktívát using ContosoPizza.Data; .
    2. Adjon hozzá egy direktívát using Microsoft.EntityFrameworkCore; .
    3. Adjon hozzá egy osztályszintű mezőt a PizzaContext konstruktor előtt.
    4. Módosítsa a konstruktormetódus aláírását egy PizzaContext paraméter elfogadásához.
    5. 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 AddSqliteProgram.cs-hez korábban hozzáadott metódushívás függőséginjektálásra regisztrálva PizzaContext . A példány létrehozásakor PizzaContext a PizzaService rendszer a konstruktorba injektálja a példányt.

  2. 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 ToListküldjük vissza: .
  3. 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 és Sauce a Toppings 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 a id paraméterével.
  4. 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 az newPizza 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.
  5. 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 és Sauce az objektumokra mutató hivatkozások a használatával Findjö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 az Sauce objektum.
    • A Update metódushívás szükségtelen, mert az EF Core észleli, hogy a tulajdonságot a Sauce következőre Pizzaállította be: .
    • A SaveChanges metódus arra utasítja az EF Core-t, hogy őrizhesse meg az adatbázis objektummódosításait.
  6. 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 és Topping az objektumokra mutató hivatkozások a használatával Findjönnek létre.
    • Az Topping objektum a metódussal lesz hozzáadva a Pizza.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.
  7. 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 az Id esetben).
    • A Remove metódus eltávolítja az entitást az pizzaToDelete 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.
  8. 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.

  1. Az Adatok mappában adjon hozzá egy dbInitializer.cs nevű új fájlt.

  2. 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 a Initialize metódus is a következőként van definiálva: static.
    • Initialize paraméterként fogad el egy PizzaContext objektumot.
    • Ha a három tábla egyikében sem található rekord, Pizzaa , Sauceés Topping az objektumok létrejönnek.
    • Az Pizza objektumok (és azok SauceTopping navigációs tulajdonságai) az objektumgráfhoz a használatával lesznek hozzáadva AddRange.
    • Az objektumgráf módosításait a használatával véglegesíteni kell az adatbázis számára SaveChanges.

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 IHostDbInitializer.Initialize:

  1. Az Adatok mappában adjon hozzá egy Extensions.cs nevű új fájlt.

  2. 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ént IHostvan 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. Az PizzaContext objektum paraméterként lesz átadva.

  3. 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.

  4. 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.

Tesztelje tudását

1.

Tegyük fel, hogy csak olvasási lekérdezést szeretne írni. Hogyan jelzi az EF Core számára, hogy nincs szükség az objektumdiagram-módosítások követésére?