Zarządzanie migracjami

W miarę zmian modelu migracje są dodawane i usuwane w ramach normalnego programowania, a pliki migracji są ewidencjona w kontroli źródła projektu. Aby zarządzać migracjami, należy najpierw zainstalować narzędzia wiersza polecenia platformy EF Core.

Napiwek

Jeśli element DbContext znajduje się w innym zestawie niż projekt startowy, możesz jawnie określić projekty docelowe i startowe w narzędziach konsoli Menedżer pakietów lub narzędziach interfejsu wiersza polecenia platformy .NET Core.

Dodawanie migracji

Po zmianie modelu możesz dodać migrację dla tej zmiany:

dotnet ef migrations add AddBlogCreatedTimestamp

Nazwa migracji może być używana jak komunikat zatwierdzenia w systemie kontroli wersji. Możesz na przykład wybrać nazwę, taką jak AddBlogCreatedTimestamp , jeśli zmiana jest nową CreatedTimestamp właściwością Blog jednostki.

Trzy pliki są dodawane do projektu w katalogu Migrations :

  • XXXXXXXXXXXXXX_AddCreatedTimestamp.cs--Główny plik migracji. Zawiera operacje niezbędne do zastosowania migracji (w Uppliku ) i do jego przywracania (w pliku Down).
  • XXXXXXXXXXXXXX_AddCreatedTimestamp. Projektant.cs--Plik metadanych migracji. Zawiera informacje używane przez program EF.
  • MyContextModelSnapshot.cs--A migawka bieżącego modelu. Służy do określania zmian podczas dodawania następnej migracji.

Sygnatura czasowa w nazwie pliku pomaga zachować ich uporządkowaną chronologicznie, dzięki czemu można zobaczyć postęp zmian.

Przestrzenie nazw

Możesz przenieść pliki Migrations i ręcznie zmienić ich przestrzeń nazw. Nowe migracje są tworzone jako częścią równorzędną ostatniej migracji. Alternatywnie można określić katalog w czasie generowania w następujący sposób:

dotnet ef migrations add InitialCreate --output-dir Your/Directory

Uwaga

Przestrzeń nazw można również zmienić niezależnie od katalogu przy użyciu polecenia --namespace.

Dostosowywanie kodu migracji

Podczas gdy program EF Core zazwyczaj tworzy dokładne migracje, należy zawsze przejrzeć kod i upewnić się, że odpowiada to żądanej zmianie; w niektórych przypadkach konieczne jest nawet zrobienie tego.

Zmiany nazw kolumn

Jednym z godnych uwagi przykładem, w którym wymagane jest dostosowanie migracji, jest zmiana nazwy właściwości. Jeśli na przykład zmienisz nazwę właściwości z Name na FullName, program EF Core wygeneruje następującą migrację:

migrationBuilder.DropColumn(
    name: "Name",
    table: "Customers");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customers",
    nullable: true);

Program EF Core zazwyczaj nie może wiedzieć, kiedy zamiarem jest usunięcie kolumny i utworzenie nowej (dwóch oddzielnych zmian) oraz zmiana nazwy kolumny. Jeśli powyższa migracja zostanie zastosowana zgodnie z rzeczywistym użyciem, wszystkie twoje nazwy klientów zostaną utracone. Aby zmienić nazwę kolumny, zastąp powyższą wygenerowaną migrację następującymi elementami:

migrationBuilder.RenameColumn(
    name: "Name",
    table: "Customers",
    newName: "FullName");

Napiwek

Proces tworzenia szkieletu migracji ostrzega, gdy operacja może spowodować utratę danych (na przykład usunięcie kolumny). Jeśli widzisz to ostrzeżenie, pamiętaj, aby przejrzeć kod migracji pod kątem dokładności.

Dodawanie nieprzetworzonego kodu SQL

Zmiana nazwy kolumny można osiągnąć za pomocą wbudowanego interfejsu API, w wielu przypadkach, które nie są możliwe. Na przykład możemy zastąpić istniejące FirstName właściwości i LastName pojedynczą, nową FullName właściwością. Migracja wygenerowana przez program EF Core będzie następująca:

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

Tak jak wcześniej, spowodowałoby to niepożądane utratę danych. Aby przenieść dane ze starych kolumn, zmieniamy kolejność migracji i wprowadzamy nieprzetworzone operacje SQL w następujący sposób:

migrationBuilder.AddColumn<string>(
    name: "FullName",
    table: "Customer",
    nullable: true);

migrationBuilder.Sql(
@"
    UPDATE Customer
    SET FullName = FirstName + ' ' + LastName;
");

migrationBuilder.DropColumn(
    name: "FirstName",
    table: "Customer");

migrationBuilder.DropColumn(
    name: "LastName",
    table: "Customer");

Dowolne zmiany za pośrednictwem nieprzetworzonego kodu SQL

Nieprzetworzona baza danych SQL może również służyć do zarządzania obiektami bazy danych, których nie zna program EF Core. W tym celu dodaj migrację bez wprowadzania żadnych zmian w modelu; Zostanie wygenerowana pusta migracja, którą można następnie wypełnić nieprzetworzonymi operacjami SQL.

Na przykład poniższa migracja tworzy procedurę składowaną programu SQL Server:

migrationBuilder.Sql(
@"
    EXEC ('CREATE PROCEDURE getFullName
        @LastName nvarchar(50),
        @FirstName nvarchar(50)
    AS
        RETURN @LastName + @FirstName;')");

Napiwek

EXEC jest używany, gdy instrukcja musi być pierwszą lub tylko jedną w partii SQL. Można go również użyć do obejścia błędów analizatora w skryptach migracji idempotentnych, które mogą wystąpić, gdy przywoływanych kolumn nie istnieją obecnie w tabeli.

Może to służyć do zarządzania dowolnym aspektem bazy danych, w tym:

  • Procedury składowane
  • Wyszukiwanie pełnotekstowe
  • Funkcje
  • Wyzwalacze
  • Widoki

W większości przypadków program EF Core automatycznie opakowuje każdą migrację we własnej transakcji podczas stosowania migracji. Niestety niektórych operacji migracji nie można wykonać w ramach transakcji w niektórych bazach danych; w takich przypadkach możesz zrezygnować z transakcji, przekazując suppressTransaction: true do .migrationBuilder.Sql

Usuwanie migracji

Czasami dodajesz migrację i zdajesz sobie sprawę, że musisz wprowadzić dodatkowe zmiany w modelu EF Core przed jego zastosowaniem. Aby usunąć ostatnią migrację, użyj tego polecenia.

dotnet ef migrations remove

Po usunięciu migracji możesz wprowadzić dodatkowe zmiany modelu i dodać go ponownie.

Ostrzeżenie

Unikaj usuwania wszelkich migracji, które zostały już zastosowane do produkcyjnych baz danych. Oznacza to, że nie będzie można przywrócić tych migracji z baz danych i może spowodować przerwanie założeń dokonanych przez kolejne migracje.

Wyświetlanie listy migracji

Możesz wyświetlić listę wszystkich istniejących migracji w następujący sposób:

dotnet ef migrations list

Sprawdzanie oczekujących zmian modelu

Uwaga

Ta funkcja została dodana w programie EF Core 8.0.

Czasami warto sprawdzić, czy od ostatniej migracji nastąpiły jakieś zmiany modelu. Może to pomóc ci wiedzieć, kiedy ty lub kolega z zespołu zapomnieli dodać migrację. Jednym ze sposobów, aby to zrobić, jest użycie tego polecenia.

dotnet ef migrations has-pending-model-changes

Możesz również wykonać to sprawdzanie programowo przy użyciu polecenia context.Database.HasPendingModelChanges(). Może to służyć do pisania testu jednostkowego, który kończy się niepowodzeniem, gdy zapomnisz dodać migrację.

Resetowanie wszystkich migracji

W niektórych skrajnych przypadkach może być konieczne usunięcie wszystkich migracji i rozpoczęcie od nowa. Można to łatwo zrobić, usuwając folder Migrations i upuszczając bazę danych. W tym momencie można utworzyć nową migrację początkową, która będzie zawierać cały bieżący schemat.

Istnieje również możliwość zresetowania wszystkich migracji i utworzenia pojedynczego bez utraty danych. Jest to czasami nazywane "squashing" i obejmuje pewną pracę ręczną:

  1. Wykonaj kopię zapasową bazy danych, jeśli coś pójdzie nie tak.
  2. W bazie danych usuń wszystkie wiersze z tabeli historii migracji (np. DELETE FROM [__EFMigrationsHistory] w programie SQL Server).
  3. Usuń folder Migrations.
  4. Utwórz nową migrację i wygeneruj dla niego skrypt SQL (dotnet ef migrations script).
  5. Wstaw pojedynczy wiersz do historii migracji, aby zarejestrować, że pierwsza migracja została już zastosowana, ponieważ tabele już istnieją. Wstaw sql jest ostatnią operacją w skrycie SQL wygenerowaną powyżej i przypomina następujące (nie zapomnij zaktualizować wartości):
INSERT INTO [__EFMigrationsHistory] ([MIGRATIONID], [PRODUCTVERSION])
VALUES (N'<full_migration_timestamp_and_name>', N'<EF_version>');

Ostrzeżenie

Każdy niestandardowy kod migracji zostanie utracony po usunięciu folderu Migrations . Aby można było zachować wszystkie dostosowania, należy ręcznie zastosować do nowej migracji początkowej.

Dodatkowe zasoby