Ćwiczenie — konfigurowanie migracji

Ukończone

W tej lekcji utworzysz klasy jednostek języka C#, które mapujesz na tabele w lokalnej bazie danych SQLite. Funkcja migracji programu EF Core tworzy tabele z tych jednostek.

Migracja umożliwia przyrostowe aktualizowanie schematu bazy danych.

Pobieranie plików projektu

Aby rozpocząć, pobierz pliki projektu. Dostępne są pewne opcje pobierania plików projektu:

  • Korzystanie z usługi GitHub Codespaces
  • Sklonuj repozytorium GitHub

Jeśli masz zainstalowane zgodne środowisko uruchomieniowe kontenera, możesz również użyć rozszerzenia Dev Containers , aby otworzyć repozytorium w kontenerze z wstępnie zainstalowanymi narzędziami.

Korzystanie z usługi GitHub Codespaces

Codespace to środowisko IDE hostowane w chmurze. Jeśli używasz usługi GitHub Codespaces, przejdź do repozytorium w przeglądarce. Wybierz pozycję Kod, a następnie utwórz nową przestrzeń kodu w main gałęzi .

Sklonuj repozytorium GitHub

Jeśli nie używasz usługi GitHub Codespaces, możesz sklonować repozytorium GitHub projektu, a następnie otworzyć pliki jako folder w programie Visual Studio Code.

  1. Otwórz terminal poleceń, a następnie sklonuj projekt z usługi GitHub przy użyciu wiersza polecenia:

    git clone https://github.com/MicrosoftDocs/mslearn-persist-data-ef-core
    
  2. Przejdź do folderu mslearn-persist-data-ef-core , a następnie otwórz projekt w programie Visual Studio Code:

    cd mslearn-persist-data-ef-core
    code .
    

Przeglądanie kodu

Teraz, gdy masz pliki projektu do pracy, zobaczmy, co znajduje się w projekcie i przejrzyjmy kod.

  • Projekt internetowego interfejsu API platformy ASP.NET Core znajduje się w katalogu ContosoPizza . Ścieżki plików, do których odwołujemy się w tym module, są względem katalogu ContosoPizza .
  • Services/PizzaService.cs to klasa usługi, która definiuje metody tworzenia, odczytu, aktualizacji i usuwania (CRUD). Wszystkie metody obecnie zgłaszają wartość System.NotImplementedException.
  • W Program.csPizzaService jest rejestrowany w systemie wstrzykiwania zależności ASP.NET Core.
  • Kontrolery/PizzaController.cs to wartość ApiController , która uwidacznia punkt końcowy dla zleceń HTTP POST, GET, PUT i DELETE. Te czasowniki nazywają odpowiednie metody CRUD na .PizzaService PizzaService jest wstrzykiwany do konstruktora PizzaController .
  • Folder Models zawiera modele, które PizzaService i PizzaController używają.
  • Modele jednostek, Pizza.cs, Topping.cs i Sauce.cs mają następujące relacje:
    • Pizza może mieć co najmniej jeden dodatek.
    • Topping może być używany na jednej lub na wielu pizzach.
    • Pizza może mieć jeden sos, ale sos może być używany na wielu pizzach.

Tworzenie aplikacji

Aby skompilować aplikację w programie Visual Studio Code:

  1. W okienku Eksplorator kliknij prawym przyciskiem myszy katalog ContosoPizza i wybierz polecenie Otwórz w zintegrowanym terminalu.

    Zostanie otwarte okienko terminalu z zakresem katalogu ContosoPizza .

  2. Skompiluj aplikację przy użyciu następującego polecenia:

    dotnet build
    

    Kod powinien być kompilować bez ostrzeżeń ani błędów.

Dodawanie pakietów NuGet i narzędzi EF Core

Aparat bazy danych, z którym pracujesz w tym module, to SQLite. SQLite to lekki, oparty na plikach aparat bazy danych. Jest to dobry wybór w przypadku programowania i testowania, a także jest dobrym wyborem w przypadku wdrożeń produkcyjnych na małą skalę.

Uwaga

Jak wspomniano wcześniej, dostawcy baz danych w programie EF Core są podłączane. SqLite jest dobrym wyborem dla tego modułu, ponieważ jest lekki i międzyplatformowy. Możesz użyć tego samego kodu, aby pracować z różnymi aparatami baz danych, takimi jak SQL Server i PostgreSQL. Można nawet użyć wielu aparatów baz danych w tej samej aplikacji.

Przed rozpoczęciem dodaj wymagane pakiety:

  1. W okienku terminalu uruchom następujące polecenie:

    dotnet add package Microsoft.EntityFrameworkCore.Sqlite
    

    To polecenie dodaje pakiet NuGet zawierający dostawcę bazy danych EF Core SQLite i wszystkie jego zależności, w tym typowe usługi EF Core.

  2. Następnie uruchom następujące polecenie:

    dotnet add package Microsoft.EntityFrameworkCore.Design
    

    To polecenie dodaje pakiety wymagane dla narzędzi EF Core.

  3. Aby zakończyć, uruchom następujące polecenie:

    dotnet tool install --global dotnet-ef
    

    To polecenie instaluje dotnet efnarzędzie , które służy do tworzenia migracji i tworzenia szkieletów.

    Napiwek

    Jeśli dotnet ef jest już zainstalowany, możesz go zaktualizować, uruchamiając polecenie dotnet tool update --global dotnet-ef.

Modele szkieletów i DbContext

Teraz dodasz i skonfigurujesz implementację DbContext . DbContext to brama, za pomocą której można wchodzić w interakcje z bazą danych.

  1. Kliknij prawym przyciskiem myszy katalog ContosoPizza i dodaj nowy folder o nazwie Dane.

  2. W folderze Dane utwórz nowy plik o nazwie PizzaContext.cs. Dodaj następujący kod do pustego pliku:

    using Microsoft.EntityFrameworkCore;
    using ContosoPizza.Models;
    
    namespace ContosoPizza.Data;
    
    public class PizzaContext : DbContext
    {
        public PizzaContext (DbContextOptions<PizzaContext> options)
            : base(options)
        {
        }
    
        public DbSet<Pizza> Pizzas => Set<Pizza>();
        public DbSet<Topping> Toppings => Set<Topping>();
        public DbSet<Sauce> Sauces => Set<Sauce>();
    }
    

    Powyższy kod:

    • Konstruktor akceptuje parametr typu DbContextOptions<PizzaContext>. Konstruktor umożliwia przekazywanie kodu zewnętrznego w konfiguracji w taki sposób, aby ten sam DbContext mógł być współużytkowany między kodem testowym i produkcyjnym, a nawet używany z różnymi dostawcami.
    • Właściwości DbSet<T> odpowiadają tabelom do utworzenia w bazie danych.
    • Nazwy tabel są zgodne z DbSet<T> nazwami właściwości w PizzaContext klasie. To zachowanie można zastąpić w razie potrzeby.
    • Po utworzeniu Pizzaswystąpienia PizzaContext program uwidacznia właściwości , Toppingsi Sauces . Zmiany wprowadzone w kolekcjach, które te właściwości uwidaczniają, są propagowane do bazy danych.
  3. W Program.cs zastąp // Add the PizzaContext ciąg następującym kodem:

    builder.Services.AddSqlite<PizzaContext>("Data Source=ContosoPizza.db");
    

    Powyższy kod ma następujące działanie:

    • Rejestruje się PizzaContext w systemie wstrzykiwania zależności ASP.NET Core.
    • Określa, że PizzaContext używa dostawcy bazy danych SQLite.
    • Definiuje parametry połączenia SQLite wskazującą plik lokalny ContosoPizza.db.

    Uwaga

    SqLite używa lokalnych plików bazy danych, więc dobrze jest zakodować parametry połączenia. W przypadku sieciowych baz danych, takich jak PostgreSQL i SQL Server, zawsze należy bezpiecznie przechowywać parametry połączenia. W przypadku programowania lokalnego użyj programu Secret Manager. W przypadku wdrożeń produkcyjnych rozważ użycie usługi takiej jak Azure Key Vault.

  4. Również w Program.cs zastąp // Additional using declarations element następującym kodem.

    using ContosoPizza.Data;
    

    Ten kod rozwiązuje zależności w poprzednim kroku.

  5. Zapisz wszystkie zmiany. Usługa GitHub Codespaces automatycznie zapisuje zmiany.

  6. Skompiluj aplikację w terminalu, uruchamiając polecenie dotnet build. Kompilacja powinna zakończyć się powodzeniem bez ostrzeżeń ani błędów.

Tworzenie i uruchamianie migracji

Następnie utwórz migrację, której można użyć do utworzenia początkowej bazy danych.

  1. W terminalu o zakresie do folderu projektu ContosoPizza uruchom następujące polecenie, aby wygenerować migrację do tworzenia tabel bazy danych:

    dotnet ef migrations add InitialCreate --context PizzaContext
    

    W powyższym poleceniu:

    • Migracja nosi nazwę: InitialCreate.
    • Opcja --context określa nazwę klasy w projekcie ContosoPizza, która wywodzi się z klasy DbContext.

    Nowy katalog Migrations pojawia się w katalogu głównym projektu ContosoPizza. Katalog zawiera plik opisujący <timestamp>_InitialCreate.cs zmiany bazy danych, które mają zostać przetłumaczone na skrypt zmiany języka definicji danych (DDL).

  2. Uruchom następujące polecenie, aby zastosować migrację InitialCreate:

    dotnet ef database update --context PizzaContext
    

    To polecenie stosuje migrację. ContosoPizza.db nie istnieje, więc to polecenie tworzy migrację w katalogu projektu.

    Napiwek

    Wszystkie platformy obsługują dotnet ef narzędzie. W programie Visual Studio w systemie Windows można użyć Add-Migration poleceń cmdlet programu i Update-Database PowerShell w zintegrowanym oknie konsoli Menedżer pakietów.

Inspekcja bazy danych

Program EF Core utworzył bazę danych dla aplikacji. Następnie przyjrzyjmy się bazie danych przy użyciu rozszerzenia SQLite.

  1. W okienku Eksplorator kliknij prawym przyciskiem myszy plik ContosoPizza.db i wybierz polecenie Otwórz bazę danych.

    Zrzut ekranu przedstawiający opcję menu Otwórz bazę danych w okienku Eksplorator programu Visual Studio Code.

    Folder SQLite Explorer zostanie wyświetlony w okienku Eksplorator .

    Zrzut ekranu przedstawiający folder SQLite Explorer w okienku Eksplorator.

  2. Wybierz folder SQLite Explorer, aby rozwinąć węzeł i wszystkie węzły podrzędne. Kliknij prawym przyciskiem myszy ContosoPizza.db i wybierz polecenie Pokaż tabelę "sqlite_master" , aby wyświetlić pełny schemat i ograniczenia bazy danych utworzone przez migrację.

    Zrzut ekranu przedstawiający rozwinięty folder SQLite Explorer w okienku Eksplorator.

    • Utworzono tabele odpowiadające każdej jednostce.
    • Nazwy tabel zostały pobrane z nazw DbSet właściwości obiektu PizzaContext.
    • Właściwości nazwane Id zostały wywnioskowane jako automatyczne zwiększanie pól klucza podstawowego.
    • Konwencje nazewnictwa klucza podstawowego i klucza obcego platformy EF Core są PK_<primary key property> odpowiednio i FK_<dependent entity>_<principal entity>_<foreign key property>. Symbole zastępcze <dependent entity> i <principal entity> odnoszą się do nazw klas jednostek.

    Uwaga

    Podobnie jak ASP.NET Core MVC, platforma EF Core używa konwencji dotyczącej podejścia do konfiguracji . Konwencje technologii EF Core skracają czas projektowania przez wnioskowanie intencji dewelopera. Na przykład program EF Core wywnioskuje właściwość o nazwie Id lub <entity name>Id jako klucz podstawowy wygenerowanej tabeli. Jeśli zdecydujesz się nie przyjąć konwencji nazewnictwa, musisz dodać adnotację do właściwości za pomocą atrybutu [Key] lub skonfigurować ją jako klucz w OnModelCreating metodzie DbContext.

Zmienianie modelu i aktualizowanie schematu bazy danych

Twój menedżer w firmie Contoso Pizza oferuje pewne nowe wymagania, więc musisz zmienić modele jednostek. W poniższych krokach zmodyfikujesz modele przy użyciu atrybutów mapowania (czasami nazywanych adnotacjami danych).

  1. W obszarze Models\Pizza.cs wprowadź następujące zmiany:

    1. Dodaj dyrektywę using dla elementu System.ComponentModel.DataAnnotations.
    2. Dodaj atrybut przed właściwością [Required] , Name aby oznaczyć właściwość zgodnie z wymaganiami.
    3. Dodaj atrybut przed właściwością [MaxLength(100)] , Name aby określić maksymalną długość ciągu 100.

    Zaktualizowany plik Pizza.cs powinien wyglądać podobnie do następującego kodu:

    using System.ComponentModel.DataAnnotations;
    
    namespace ContosoPizza.Models;
    
    public class Pizza
    {
        public int Id { get; set; }
    
        [Required]
        [MaxLength(100)]
        public string? Name { get; set; }
    
        public Sauce? Sauce { get; set; }
    
        public ICollection<Topping>? Toppings { get; set; }
    }
    
  2. W obszarze Models\Sauce.cs wprowadź następujące zmiany:

    1. Dodaj dyrektywę using dla elementu System.ComponentModel.DataAnnotations.
    2. Dodaj atrybut przed właściwością [Required] , Name aby oznaczyć właściwość zgodnie z wymaganiami.
    3. Dodaj atrybut przed właściwością [MaxLength(100)] , Name aby określić maksymalną długość ciągu 100.
    4. bool Dodaj właściwość o nazwie IsVegan.

    Zaktualizowany plik Sauce.cs powinien wyglądać podobnie do następującego kodu:

    using System.ComponentModel.DataAnnotations;
    
    namespace ContosoPizza.Models;
    
    public class Sauce
    {
        public int Id { get; set; }
    
        [Required]
        [MaxLength(100)]
        public string? Name { get; set; }
    
        public bool IsVegan { get; set; }
    }
    
  3. W obszarze Models\Topping.cs wprowadź następujące zmiany:

    1. Dodaj using dyrektywy dla System.ComponentModel.DataAnnotations i System.Text.Json.Serialization.

    2. Dodaj atrybut przed właściwością [Required] , Name aby oznaczyć właściwość zgodnie z wymaganiami.

    3. Dodaj atrybut przed właściwością [MaxLength(100)] , Name aby określić maksymalną długość ciągu 100.

    4. decimal Dodaj właściwość o nazwie Calories bezpośrednio po Name właściwości .

    5. Pizzas Dodaj właściwość typu ICollection<Pizza>?. Ta zmiana powoduje, że Pizza-Topping relacja wiele do wielu.

    6. [JsonIgnore] Dodaj atrybut do Pizzas właściwości .

      Ważne

      Ten atrybut uniemożliwia Topping jednostki dołączanie Pizzas właściwości, gdy kod internetowego interfejsu API serializuje odpowiedź na kod JSON. Bez tej zmiany serializowana kolekcja toppingów będzie zawierać kolekcję każdej pizzy, która używa toppingu. Każda pizza w tej kolekcji będzie zawierać kolekcję toppingów, które każdy będzie ponownie zawierać kolekcję pizzy. Ten typ pętli nieskończonej jest nazywany odwołaniem okrągłym i nie może być serializowany.

    Zaktualizowany plik Topping.cs powinien wyglądać podobnie do następującego kodu:

    using System.ComponentModel.DataAnnotations;
    using System.Text.Json.Serialization;
    
    namespace ContosoPizza.Models;
    
    public class Topping
    {
        public int Id { get; set; }
    
        [Required]
        [MaxLength(100)]
        public string? Name { get; set; }
    
        public decimal Calories { get; set; }
    
        [JsonIgnore]
        public ICollection<Pizza>? Pizzas { get; set; }
    }
    
  4. Zapisz wszystkie zmiany i uruchom polecenie dotnet build.

  5. Uruchom następujące polecenie, aby wygenerować migrację w celu utworzenia tabel bazy danych:

    dotnet ef migrations add ModelRevisions --context PizzaContext
    

    To polecenie tworzy migrację o nazwie : ModelRevisions.

    Uwaga

    Zostanie wyświetlony następujący komunikat: Operacja została utworzona szkieletem, co może spowodować utratę danych. Przejrzyj migrację pod kątem dokładności. Ten komunikat pojawił się, ponieważ zmieniono relację z Pizza Topping z "jeden do wielu" na wiele-do-wielu, co wymaga porzucenia istniejącej kolumny klucza obcego. Ponieważ nie masz jeszcze żadnych danych w bazie danych, ta zmiana nie jest problematyczna. Jednak ogólnie rzecz biorąc, dobrym pomysłem jest sprawdzenie wygenerowanej migracji po wyświetleniu tego ostrzeżenia, aby upewnić się, że migracja nie usuwa ani nie obcina żadnych danych.

  6. Uruchom następujące polecenie, aby zastosować migrację ModelRevisions:

    dotnet ef database update --context PizzaContext
    
  7. Na pasku tytułu folderu SQLite Explorer wybierz przycisk Odśwież bazy danych .

    Zrzut ekranu przedstawiający przycisk Odśwież bazy danych na pasku tytułu eksploratora SQLite Explorer.

  8. W folderze SQLite Explorer kliknij prawym przyciskiem myszy ContosoPizza.db. Wybierz pozycję Pokaż tabelę "sqlite_master" , aby wyświetlić pełny schemat i ograniczenia bazy danych.

    Ważne

    Rozszerzenie SQLite ponownie używa otwartych kart SQLite .

    • Utworzono tabelę PizzaTopping sprzężenia reprezentującą relację wiele-do-wielu między pizzami i toppingami.
    • Dodano nowe pola do Toppings i Sauces.
      • Calories jest definiowana jako kolumna text , ponieważ sqlite nie ma pasującego decimal typu.
      • IsVegan Podobnie jest definiowana jako kolumnainteger. SqLite nie definiuje bool typu.
      • W obu przypadkach program EF Core zarządza tłumaczeniem.
    • Kolumna Name w każdej tabeli została oznaczona jako not null, ale sqlite nie ma MaxLength ograniczenia.

    Napiwek

    Dostawcy baz danych platformy EF Core mapować schemat modelu na funkcje określonej bazy danych. Mimo że sqLite nie implementuje odpowiedniego ograniczenia dla MaxLength, inne bazy danych, takie jak SQL Server i PostgreSQL, robią.

  9. W folderze SQLite Explorer kliknij prawym przyciskiem myszy tabelę _EFMigrationsHistory i wybierz polecenie Pokaż tabelę. Tabela zawiera listę wszystkich migracji zastosowanych do bazy danych. Ponieważ uruchomiono dwie migracje, istnieją dwa wpisy: jeden dla migracji InitialCreate , a drugi dla modeluRevisions.

Uwaga

W tym ćwiczeniu użyto atrybutów mapowania (adnotacji danych) do mapowania modeli na bazę danych. Alternatywą dla atrybutów mapowania jest użycie płynnego interfejsu API ModeluBuilder do konfigurowania modeli. Oba podejścia są prawidłowe, ale niektórzy deweloperzy wolą jedno podejście nad drugim.

Migracje były używane do definiowania i aktualizowania schematu bazy danych. W następnej lekcji dokończysz metody, które PizzaService manipulują danymi.

Sprawdź swoją wiedzę

1.

Jaka jest konwencja nazewnictwa dla klucza podstawowego w klasie jednostki?