Udostępnij za pośrednictwem


Zarządzanie migracjami

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

Wskazówka

Jeśli DbContext znajduje się w innym zestawie niż projekt startowy, możesz wyraźnie określić projekty startowe i docelowe w narzędziach konsoli menedżera pakietów lub narzędziach CLI 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ą właściwością CreatedTimestamp w jednostce Blog.

Do projektu są dodawane trzy pliki w katalogu Migrations:

  • XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.cs— główny plik migracji. Zawiera operacje niezbędne do zastosowania migracji (w Up) i jej cofnięcia (w Down).
  • XXXXXXXXXXXXXX_AddBlogCreatedTimestamp.Designer.cs--Plik metadanych migracji. Zawiera informacje używane przez program EF.
  • MyContextModelSnapshot.cs— migawka bieżącego modelu. Używane do określenia, co się zmieniło podczas dodawania kolejnej 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 równorzędne z ostatnią migracją. 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 --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 as-is, nazwy Twoich 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");

Wskazówka

Proces tworzenia szablonu 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

Zmianę nazwy kolumny można osiągnąć za pomocą wbudowanego interfejsu API, jednak w wielu przypadkach nie jest to możliwe. Na przykład możemy zastąpić istniejące właściwości FirstName i LastName pojedynczą, nową właściwością FullName. 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;')");

Wskazówka

EXEC jest używana, gdy instrukcja musi być pierwszą lub jedyną 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 przechowywane
  • Wyszukiwanie pełnotekstowe
  • Funkcje
  • Wyzwalaczy
  • 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 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. Aby zarejestrować, że pierwsza migracja została już zastosowana, wstaw pojedynczy wiersz do historii migracji, ponieważ tabele już istnieją. Wstawianie SQL jest ostatnią operacją w skrypcie SQL wygenerowanym 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

Wszystkie niestandardowe kody migracji zostaną utracone po usunięciu folderu Migrations. Aby zachować wszystkie dostosowania, należy je ręcznie zastosować do nowej migracji początkowej.

Dodatkowe zasoby