Część 4. Razor Strony z migracjami EF Core w ASP.NET Core
Przez Tom Dykstra, Jon P Smith i Rick Anderson
Aplikacja internetowa Contoso University pokazuje, jak tworzyć Razor aplikacje internetowe stron przy użyciu programu EF Core Visual Studio. Aby uzyskać informacje na temat serii samouczków, zobacz pierwszy samouczek.
Jeśli napotkasz problemy, których nie możesz rozwiązać, pobierz ukończoną aplikację i porównaj ten kod z utworzonymi elementami, wykonując czynności opisane w samouczku.
W tym samouczku przedstawiono EF Core funkcję migracji na potrzeby zarządzania zmianami modelu danych.
Podczas tworzenia nowej aplikacji model danych zmienia się często. Za każdym razem, gdy model zmienia się, model nie jest synchronizowany z bazą danych. Ta seria samouczków została uruchomiona przez skonfigurowanie programu Entity Framework w celu utworzenia bazy danych, jeśli nie istnieje. Za każdym razem, gdy zmienia się model danych, baza danych musi zostać porzucona. Przy następnym uruchomieniu aplikacji wywołanie w celu EnsureCreated
ponownego utworzenia bazy danych w celu dopasowania do nowego modelu danych. Następnie DbInitializer
klasa jest uruchamiana w celu zainicjowania nowej bazy danych.
Takie podejście do zachowania synchronizacji bazy danych z modelem danych działa dobrze do momentu wdrożenia aplikacji w środowisku produkcyjnym. Gdy aplikacja jest uruchomiona w środowisku produkcyjnym, zwykle przechowuje dane, które muszą być przechowywane. Aplikacja nie może rozpoczynać się od testowej bazy danych za każdym razem, gdy zostanie wprowadzona zmiana (na przykład dodanie nowej kolumny). Funkcja EF Core Migracje rozwiązuje ten problem, umożliwiając EF Core aktualizowanie schematu bazy danych zamiast tworzenia nowej bazy danych.
Zamiast usuwać i ponownie utworzyć bazę danych po zmianie modelu danych, migracje aktualizują schemat i zachowują istniejące dane.
Uwaga
Ograniczenia sqlite
W tym samouczku jest używana funkcja migracji platformy Entity Framework Core tam, gdzie to możliwe. Migracje aktualizują schemat bazy danych w celu dopasowania zmian w modelu danych. Jednak migracje robią tylko rodzaje zmian, które obsługuje aparat bazy danych, a możliwości zmiany schematu SQLite są ograniczone. Na przykład dodawanie kolumny jest obsługiwane, ale usuwanie kolumny nie jest obsługiwane. Jeśli migracja zostanie utworzona w celu usunięcia kolumny, polecenie zakończy się powodzeniem, ef migrations add
ale polecenie zakończy się niepowodzeniem ef database update
.
Obejściem ograniczeń SQLite jest ręczne napisanie kodu migracji w celu ponownego skompilowania tabeli, gdy coś się zmieni w tabeli. Kod przechodzi do Up
metod i Down
migracji i obejmuje:
- Tworzenie nowej tabeli.
- Kopiowanie danych ze starej tabeli do nowej tabeli.
- Upuszczanie starej tabeli.
- Zmiana nazwy nowej tabeli.
Pisanie kodu specyficznego dla bazy danych tego typu wykracza poza zakres tego samouczka. Zamiast tego ten samouczek przerywa i ponownie tworzy bazę danych za każdym razem, gdy próba zastosowania migracji zakończy się niepowodzeniem. Aby uzyskać więcej informacji, zobacz następujące zasoby:
Usuwanie bazy danych
Użyj programu SQL Server Eksplorator obiektów (SSOX), aby usunąć bazę danych, lub uruchom następujące polecenie w konsoli Menedżer pakietów (PMC):
Drop-Database
Tworzenie migracji początkowej
Uruchom następujące polecenia w usłudze PMC:
Add-Migration InitialCreate
Update-Database
Usuń upewnij się, że utworzono
Ta seria samouczków została uruchomiona przy użyciu polecenia EnsureCreated. EnsureCreated
nie tworzy tabeli historii migracji, dlatego nie można jej używać z migracjami. Jest ona przeznaczona do testowania lub szybkiego tworzenia prototypów, w których baza danych jest porzucana i często tworzona.
Od tego momentu samouczki będą korzystać z migracji.
W Program.cs
pliku usuń następujący wiersz:
context.Database.EnsureCreated();
Uruchom aplikację i sprawdź, czy baza danych jest rozstawiona.
Metody w górę i w dół
Polecenie EF Coremigrations add
wygenerowało kod do utworzenia bazy danych. Ten kod migracji znajduje się w Migrations\<timestamp>_InitialCreate.cs
pliku . Metoda Up
InitialCreate
klasy tworzy tabele bazy danych, które odpowiadają zestawom jednostek modelu danych. Metoda Down
usuwa je, jak pokazano w poniższym przykładzie:
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
namespace ContosoUniversity.Migrations
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});
migrationBuilder.CreateTable(
name: "Student",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
LastName = table.Column<string>(nullable: true),
FirstMidName = table.Column<string>(nullable: true),
EnrollmentDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Student", x => x.ID);
});
migrationBuilder.CreateTable(
name: "Enrollment",
columns: table => new
{
EnrollmentID = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
CourseID = table.Column<int>(nullable: false),
StudentID = table.Column<int>(nullable: false),
Grade = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Enrollment", x => x.EnrollmentID);
table.ForeignKey(
name: "FK_Enrollment_Course_CourseID",
column: x => x.CourseID,
principalTable: "Course",
principalColumn: "CourseID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Enrollment_Student_StudentID",
column: x => x.StudentID,
principalTable: "Student",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Enrollment_CourseID",
table: "Enrollment",
column: "CourseID");
migrationBuilder.CreateIndex(
name: "IX_Enrollment_StudentID",
table: "Enrollment",
column: "StudentID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");
migrationBuilder.DropTable(
name: "Course");
migrationBuilder.DropTable(
name: "Student");
}
}
}
Powyższy kod dotyczy migracji początkowej. Kod:
- Został wygenerowany przez
migrations add InitialCreate
polecenie . - Jest wykonywany przez
database update
polecenie . - Tworzy bazę danych dla modelu danych określonego przez klasę kontekstu bazy danych.
Parametr nazwy migracji (InitialCreate
w przykładzie) jest używany dla nazwy pliku. Nazwa migracji może być dowolną prawidłową nazwą pliku. Najlepiej wybrać słowo lub frazę podsumowującą czynności wykonywane w migracji. Na przykład migracja, która dodała tabelę działów, może mieć nazwę "AddDepartmentTable".
Tabela historii migracji
- Użyj narzędzia SSOX lub SQLite, aby sprawdzić bazę danych.
- Zwróć uwagę na dodanie
__EFMigrationsHistory
tabeli. Tabela__EFMigrationsHistory
śledzi, które migracje zostały zastosowane do bazy danych. - Wyświetl dane w
__EFMigrationsHistory
tabeli. Przedstawia jeden wiersz dla pierwszej migracji.
Migawka modelu danych
Migracje tworzy migawkę bieżącego modelu danych w programie Migrations/SchoolContextModelSnapshot.cs
. Po dodaniu migracji program EF określa, co zmieniło się, porównując bieżący model danych z plikiem migawki.
Ponieważ plik migawki śledzi stan modelu danych, nie można usunąć migracji przez usunięcie <timestamp>_<migrationname>.cs
pliku. Aby wycofać najnowszą migrację migrations remove
, użyj polecenia . migrations remove
Usuwa migrację i gwarantuje, że migawka zostanie poprawnie zresetowana. Aby uzyskać więcej informacji, zobacz dotnet ef migrations remove (Usuwanie migracji platformy dotnet ef).
Zobacz Resetowanie wszystkich migracji, aby usunąć wszystkie migracje .
Stosowanie migracji w środowisku produkcyjnym
Zalecamy, aby aplikacje produkcyjne nie wywoływać elementu Database.Migrate podczas uruchamiania aplikacji. Migrate
nie należy wywoływać z aplikacji wdrożonej w farmie serwerów. Jeśli aplikacja jest skalowana w poziomie do wielu wystąpień serwera, trudno jest upewnić się, że aktualizacje schematu bazy danych nie są wykonywane z wielu serwerów ani nie powodują konfliktu z dostępem do odczytu/zapisu.
Migracja bazy danych powinna odbywać się w ramach wdrażania i w kontrolowany sposób. Metody migracji produkcyjnej bazy danych obejmują:
- Używanie migracji do tworzenia skryptów SQL i używania skryptów SQL we wdrożeniu.
- Uruchamianie
dotnet ef database update
z kontrolowanego środowiska.
Rozwiązywanie problemów
Jeśli aplikacja używa bazy danych SQL Server LocalDB i wyświetla następujący wyjątek:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.
Rozwiązaniem może być uruchomienie dotnet ef database update
w wierszu polecenia.
Dodatkowe zasoby
- EF Core Interfejs wiersza polecenia.
- polecenia interfejsu wiersza polecenia dotnet ef migrations
- Konsola menedżera pakietów (Visual Studio)
Następne kroki
W następnym samouczku zostanie utworzony model danych, dodając właściwości jednostki i nowe jednostki.
W tym samouczku EF Core jest używana funkcja migracji do zarządzania zmianami modelu danych.
Jeśli napotkasz problemy, których nie możesz rozwiązać, pobierz ukończoną aplikację.
Podczas tworzenia nowej aplikacji model danych zmienia się często. Za każdym razem, gdy model zmienia się, model nie jest synchronizowany z bazą danych. W tym samouczku rozpoczęto konfigurowanie programu Entity Framework w celu utworzenia bazy danych, jeśli nie istnieje. Za każdym razem, gdy zmienia się model danych:
- Baza danych została porzucona.
- Program EF tworzy nowy, który jest zgodny z modelem.
- Aplikacja wysiewuje bazę danych z danymi testowymi.
Takie podejście do zachowania synchronizacji bazy danych z modelem danych działa dobrze do momentu wdrożenia aplikacji w środowisku produkcyjnym. Gdy aplikacja jest uruchomiona w środowisku produkcyjnym, zwykle przechowuje dane, które muszą być przechowywane. Aplikacja nie może rozpoczynać się od testowej bazy danych za każdym razem, gdy zostanie wprowadzona zmiana (na przykład dodanie nowej kolumny). Funkcja EF Core Migracje rozwiązuje ten problem, umożliwiając EF Core aktualizowanie schematu bazy danych zamiast tworzenia nowej bazy danych.
Zamiast usuwać i ponownie utworzyć bazę danych po zmianie modelu danych, migracje aktualizują schemat i zachowują istniejące dane.
Usuwanie bazy danych
Użyj Eksplorator obiektów programu SQL Server (SSOX) lub database drop
polecenia:
W konsoli Menedżer pakietów (PMC) uruchom następujące polecenie:
Drop-Database
Uruchom polecenie Get-Help about_EntityFrameworkCore
z pmC, aby uzyskać informacje pomocy.
Tworzenie początkowej migracji i aktualizowanie bazy danych
Skompiluj projekt i utwórz pierwszą migrację.
Add-Migration InitialCreate
Update-Database
Badanie metod w górę i w dół
Polecenie EF Coremigrations add
wygenerowało kod do utworzenia bazy danych. Ten kod migracji znajduje się w Migrations\<timestamp>_InitialCreate.cs
pliku . Metoda Up
InitialCreate
klasy tworzy tabele bazy danych, które odpowiadają zestawom jednostek modelu danych. Metoda Down
usuwa je, jak pokazano w poniższym przykładzie:
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Course",
columns: table => new
{
CourseID = table.Column<int>(nullable: false),
Title = table.Column<string>(nullable: true),
Credits = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Course", x => x.CourseID);
});
migrationBuilder.CreateTable(
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Enrollment");
migrationBuilder.DropTable(
name: "Course");
migrationBuilder.DropTable(
name: "Student");
}
}
Migracje wywołuje metodę Up
implementowania zmian modelu danych na potrzeby migracji. Po wprowadzeniu polecenia w celu wycofania aktualizacji migracje wywołuje metodę Down
.
Powyższy kod dotyczy migracji początkowej. Ten kod został utworzony podczas uruchamiania migrations add InitialCreate
polecenia. Parametr nazwy migracji ("InitialCreate" w przykładzie) jest używany dla nazwy pliku. Nazwa migracji może być dowolną prawidłową nazwą pliku. Najlepiej wybrać słowo lub frazę podsumowującą czynności wykonywane w migracji. Na przykład migracja, która dodała tabelę działów, może mieć nazwę "AddDepartmentTable".
Jeśli migracja początkowa zostanie utworzona, a baza danych istnieje:
- Zostanie wygenerowany kod tworzenia bazy danych.
- Kod tworzenia bazy danych nie musi być uruchamiany, ponieważ baza danych jest już zgodna z modelem danych. Jeśli kod tworzenia bazy danych jest uruchamiany, nie wprowadza żadnych zmian, ponieważ baza danych jest już zgodna z modelem danych.
Po wdrożeniu aplikacji w nowym środowisku należy uruchomić kod tworzenia bazy danych, aby utworzyć bazę danych.
Wcześniej baza danych została porzucona i nie istnieje, więc migracje tworzą nową bazę danych.
Migawka modelu danych
Migracje tworzą migawkę bieżącego schematu bazy danych w programie Migrations/SchoolContextModelSnapshot.cs
. Podczas dodawania migracji program EF określa, co zmieniło się, porównując model danych z plikiem migawek.
Aby usunąć migrację, użyj następującego polecenia:
Usuwanie migracji
Polecenie remove migrations usuwa migrację i gwarantuje, że migawka zostanie poprawnie zresetowana.
Usuń pozycję Upewnij się, że utworzono i przetestuj aplikację
Do wczesnego opracowywania EnsureCreated
użyto. W tym samouczku są używane migracje. EnsureCreated
ma następujące ograniczenia:
- Pomija migracje i tworzy bazę danych i schemat.
- Nie tworzy tabeli migracji.
- Nie można używać z migracjami.
- Jest przeznaczony do testowania lub szybkiego tworzenia prototypów, w których baza danych jest porzucana i często tworzona.
Usuń EnsureCreated
:
context.Database.EnsureCreated();
Uruchom aplikację i sprawdź, czy baza danych jest rozmieszczana.
Inspekcja bazy danych
Użyj Eksplorator obiektów programu SQL Server, aby sprawdzić bazę danych. Zwróć uwagę na dodanie __EFMigrationsHistory
tabeli. Tabela __EFMigrationsHistory
śledzi, które migracje zostały zastosowane do bazy danych. Wyświetl dane w __EFMigrationsHistory
tabeli. Zawiera on jeden wiersz dla pierwszej migracji. Ostatni dziennik w poprzednim przykładzie danych wyjściowych interfejsu wiersza polecenia przedstawia instrukcję INSERT, która tworzy ten wiersz.
Uruchom aplikację i sprawdź, czy wszystko działa.
Stosowanie migracji w środowisku produkcyjnym
Zalecamy, aby aplikacje produkcyjne nie powinny wywoływać elementu Database.Migrate podczas uruchamiania aplikacji. Migrate
nie powinna być wywoływana z aplikacji w farmie serwerów. Jeśli na przykład aplikacja została wdrożona w chmurze z skalowaniem w poziomie (uruchomiono wiele wystąpień aplikacji).
Migracja bazy danych powinna odbywać się w ramach wdrażania i w kontrolowany sposób. Metody migracji produkcyjnej bazy danych obejmują:
- Używanie migracji do tworzenia skryptów SQL i używania skryptów SQL we wdrożeniu.
- Uruchamianie
dotnet ef database update
z kontrolowanego środowiska.
EF Core__MigrationsHistory
używa tabeli , aby sprawdzić, czy należy uruchomić jakiekolwiek migracje. Jeśli baza danych jest aktualna, nie zostanie uruchomiona żadna migracja.
Rozwiązywanie problemów
Pobierz ukończoną aplikację.
Aplikacja generuje następujący wyjątek:
SqlException: Cannot open database "ContosoUniversity" requested by the login.
The login failed.
Login failed for user 'user name'.
Rozwiązanie: Uruchamianie dotnet ef database update