Ćwiczenie — konfigurowanie migracji
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.
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
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.cs
PizzaService
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 konstruktoraPizzaController
. - Folder Models zawiera modele, które
PizzaService
iPizzaController
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:
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 .
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:
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.
Następnie uruchom następujące polecenie:
dotnet add package Microsoft.EntityFrameworkCore.Design
To polecenie dodaje pakiety wymagane dla narzędzi EF Core.
Aby zakończyć, uruchom następujące polecenie:
dotnet tool install --global dotnet-ef
To polecenie instaluje
dotnet ef
narzę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 poleceniedotnet 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.
Kliknij prawym przyciskiem myszy katalog ContosoPizza i dodaj nowy folder o nazwie Dane.
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 samDbContext
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 wPizzaContext
klasie. To zachowanie można zastąpić w razie potrzeby. - Po utworzeniu
Pizzas
wystąpieniaPizzaContext
program uwidacznia właściwości ,Toppings
iSauces
. Zmiany wprowadzone w kolekcjach, które te właściwości uwidaczniają, są propagowane do bazy danych.
- Konstruktor akceptuje parametr typu
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.
- Rejestruje się
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.
Zapisz wszystkie zmiany. Usługa GitHub Codespaces automatycznie zapisuje zmiany.
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.
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 klasyDbContext
.
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).
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 iUpdate-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.
W okienku Eksplorator kliknij prawym przyciskiem myszy plik ContosoPizza.db i wybierz polecenie Otwórz bazę danych.
Folder SQLite Explorer zostanie wyświetlony w okienku Eksplorator .
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ę.
- Utworzono tabele odpowiadające każdej jednostce.
- Nazwy tabel zostały pobrane z nazw
DbSet
właściwości obiektuPizzaContext
. - 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 iFK_<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 wOnModelCreating
metodzieDbContext
.
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).
W obszarze Models\Pizza.cs wprowadź następujące zmiany:
- Dodaj dyrektywę
using
dla elementuSystem.ComponentModel.DataAnnotations
. - Dodaj atrybut przed właściwością
[Required]
,Name
aby oznaczyć właściwość zgodnie z wymaganiami. - 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; } }
- Dodaj dyrektywę
W obszarze Models\Sauce.cs wprowadź następujące zmiany:
- Dodaj dyrektywę
using
dla elementuSystem.ComponentModel.DataAnnotations
. - Dodaj atrybut przed właściwością
[Required]
,Name
aby oznaczyć właściwość zgodnie z wymaganiami. - Dodaj atrybut przed właściwością
[MaxLength(100)]
,Name
aby określić maksymalną długość ciągu 100. bool
Dodaj właściwość o nazwieIsVegan
.
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; } }
- Dodaj dyrektywę
W obszarze Models\Topping.cs wprowadź następujące zmiany:
Dodaj
using
dyrektywy dlaSystem.ComponentModel.DataAnnotations
iSystem.Text.Json.Serialization
.Dodaj atrybut przed właściwością
[Required]
,Name
aby oznaczyć właściwość zgodnie z wymaganiami.Dodaj atrybut przed właściwością
[MaxLength(100)]
,Name
aby określić maksymalną długość ciągu 100.decimal
Dodaj właściwość o nazwieCalories
bezpośrednio poName
właściwości .Pizzas
Dodaj właściwość typuICollection<Pizza>?
. Ta zmiana powoduje, żePizza
-Topping
relacja wiele do wielu.[JsonIgnore]
Dodaj atrybut doPizzas
właściwości .Ważne
Ten atrybut uniemożliwia
Topping
jednostki dołączaniePizzas
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; } }
Zapisz wszystkie zmiany i uruchom polecenie
dotnet build
.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.Uruchom następujące polecenie, aby zastosować migrację ModelRevisions:
dotnet ef database update --context PizzaContext
Na pasku tytułu folderu SQLite Explorer wybierz przycisk Odśwież bazy danych .
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
iSauces
.Calories
jest definiowana jako kolumnatext
, ponieważ sqlite nie ma pasującegodecimal
typu.IsVegan
Podobnie jest definiowana jako kolumnainteger
. SqLite nie definiujebool
typu.- W obu przypadkach program EF Core zarządza tłumaczeniem.
- Kolumna
Name
w każdej tabeli została oznaczona jakonot null
, ale sqlite nie maMaxLength
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ą.- Utworzono tabelę
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.