Migracje Code First z istniejącą bazą danych

Uwaga

Tylko platforma EF4.3 — funkcje, interfejsy API itp. omówione na tej stronie zostały wprowadzone w programie Entity Framework 4.1. Jeśli korzystasz ze starszej wersji, niektóre lub wszystkie podane informacje nie mają zastosowania.

W tym artykule opisano używanie Migracje Code First z istniejącą bazą danych, która nie została utworzona przez program Entity Framework.

Uwaga

W tym artykule założono, że wiesz, jak używać Migracje Code First w podstawowych scenariuszach. Jeśli tego nie zrobisz, musisz przeczytać Migracje Code First przed kontynuowaniem.

Krok 1. Tworzenie modelu

Pierwszym krokiem będzie utworzenie modelu Code First, który jest przeznaczony dla istniejącej bazy danych. Temat Code First to an Existing Database (Kod pierwszy do istniejącej bazy danych ) zawiera szczegółowe wskazówki dotyczące tego, jak to zrobić.

Uwaga

Przed wprowadzeniem zmian w modelu, które wymagają zmian w schemacie bazy danych, należy wykonać pozostałe kroki opisane w tym temacie. Poniższe kroki wymagają synchronizacji modelu ze schematem bazy danych.

Krok 2. Włączanie migracji

Następnym krokiem jest włączenie migracji. Można to zrobić, uruchamiając polecenie Enable-Migrations w konsoli Menedżer pakietów.

To polecenie utworzy folder w rozwiązaniu o nazwie Migrations (Migracje) i umieści w nim pojedynczą klasę o nazwie Configuration (Konfiguracja). Klasa Configuration to miejsce, w którym konfigurujesz migracje dla aplikacji. Więcej informacji na ten temat można znaleźć w temacie Migracje Code First.

Krok 3. Dodawanie migracji początkowej

Po utworzeniu i zastosowaniu migracji do lokalnej bazy danych możesz również zastosować te zmiany do innych baz danych. Na przykład lokalna baza danych może być testową bazą danych i ostatecznie może chcieć zastosować zmiany do produkcyjnej bazy danych i/lub innych deweloperów testowych baz danych. Istnieją dwie opcje dla tego kroku, a wybrana opcja zależy od tego, czy schemat innych baz danych jest pusty, czy obecnie jest zgodny ze schematem lokalnej bazy danych.

  • Opcja pierwsza: użyj istniejącego schematu jako punktu początkowego. Należy użyć tego podejścia, gdy inne bazy danych, do których zostaną zastosowane migracje w przyszłości, będą miały ten sam schemat co lokalna baza danych. Możesz na przykład użyć tej opcji, jeśli lokalna testowa baza danych jest obecnie zgodna z wersją 1 produkcyjnej bazy danych i później zastosujesz te migracje, aby zaktualizować produkcyjną bazę danych do wersji 2.
  • Opcja druga: użyj pustej bazy danych jako punktu wyjścia. Należy użyć tego podejścia, gdy inne bazy danych, do których będą stosowane migracje w przyszłości, są puste (lub jeszcze nie istnieją). Możesz na przykład użyć tej opcji, jeśli zaczniesz programować aplikację przy użyciu testowej bazy danych, ale bez użycia migracji, a później chcesz utworzyć produkcyjną bazę danych od podstaw.

Opcja pierwsza: użyj istniejącego schematu jako punktu początkowego

Migracje Code First używa migawki modelu przechowywanego w najnowszej migracji w celu wykrywania zmian w modelu (szczegółowe informacje na ten temat można znaleźć w Migracje Code First w środowiskach zespołowych). Ponieważ zakładamy, że bazy danych mają już schemat bieżącego modelu, wygenerujemy pustą migrację (bez operacji), która ma bieżący model jako migawkę.

  1. Uruchom polecenie Add-Migration InitialCreate –IgnoreChanges w konsoli Menedżer pakietów. Spowoduje to utworzenie pustej migracji z bieżącym modelem jako migawką.
  2. Uruchom polecenie Update-Database w konsoli Menedżer pakietów. Spowoduje to zastosowanie migracji InitialCreate do bazy danych. Ponieważ rzeczywista migracja nie zawiera żadnych zmian, wystarczy dodać wiersz do tabeli __MigrationsHistory wskazującą, że ta migracja została już zastosowana.

Opcja druga: Użyj pustej bazy danych jako punktu początkowego

W tym scenariuszu musimy mieć możliwość utworzenia całej bazy danych od podstaw, w tym tabel, które są już obecne w naszej lokalnej bazie danych. Wygenerujemy migrację InitialCreate, która obejmuje logikę tworzenia istniejącego schematu. Następnie zmienimy istniejącą bazę danych tak, jakby ta migracja została już zastosowana.

  1. Uruchom polecenie Add-Migration InitialCreate w konsoli Menedżer pakietów. Spowoduje to utworzenie migracji w celu utworzenia istniejącego schematu.
  2. Oznacz jako komentarz cały kod w metodzie Up nowo utworzonej migracji. Pozwoli to na "zastosowanie" migracji do lokalnej bazy danych bez próby ponownego utworzenia wszystkich tabel itp., które już istnieją.
  3. Uruchom polecenie Update-Database w konsoli Menedżer pakietów. Spowoduje to zastosowanie migracji InitialCreate do bazy danych. Ponieważ rzeczywista migracja nie zawiera żadnych zmian (ponieważ tymczasowo je oznaczyliśmy jako komentarz), wystarczy dodać wiersz do tabeli __MigrationsHistory wskazującą, że ta migracja została już zastosowana.
  4. Usuń komentarz do kodu w metodzie Up. Oznacza to, że po zastosowaniu tej migracji do przyszłych baz danych schemat, który już istniał w lokalnej bazie danych, zostanie utworzony przez migracje.

Kwestie, o których należy pamiętać

Istnieje kilka rzeczy, o których należy pamiętać podczas korzystania z migracji do istniejącej bazy danych.

Nazwy domyślne/obliczeniowe mogą nie być zgodne z istniejącym schematem

Migracje jawnie określają nazwy kolumn i tabel podczas tworzenia szkieletów migracji. Istnieją jednak inne obiekty bazy danych, dla których migracje oblicza domyślną nazwę podczas stosowania migracji. Obejmuje to indeksy i ograniczenia klucza obcego. W przypadku określania wartości docelowej dla istniejącego schematu te nazwy obliczeniowe mogą nie być zgodne z tym, co rzeczywiście istnieje w bazie danych.

Oto kilka przykładów, o których należy pamiętać:

Jeśli użyto opcji "Opcja pierwsza: użyj istniejącego schematu jako punktu początkowego" z kroku 3:

  • Jeśli przyszłe zmiany w modelu wymagają zmiany lub usunięcia jednego z obiektów bazy danych o nazwie inaczej, należy zmodyfikować migrację szkieletu, aby określić poprawną nazwę. Interfejsy API migracji mają opcjonalny parametr Name, który umożliwia wykonanie tej czynności. Na przykład istniejący schemat może mieć tabelę Post z kolumną klucza obcego BlogId zawierającą indeks o nazwie IndexFk_BlogId. Jednak domyślnie migracje będą oczekiwać, że ten indeks zostanie nazwany IX_BlogId. Jeśli wprowadzisz zmianę w modelu, która spowoduje usunięcie tego indeksu, musisz zmodyfikować wywołanie rusztowanego indeksu DropIndex, aby określić nazwę IndexFk_BlogId.

Jeśli użyto opcji "Opcja druga: użyj pustej bazy danych jako punktu początkowego" z kroku 3:

  • Próba uruchomienia metody w dół początkowej migracji (tj. przywrócenie pustej bazy danych) w lokalnej bazie danych może zakończyć się niepowodzeniem, ponieważ migracje spróbują usunąć indeksy i ograniczenia klucza obcego przy użyciu nieprawidłowych nazw. Będzie to miało wpływ tylko na lokalną bazę danych, ponieważ inne bazy danych zostaną utworzone od podstaw przy użyciu metody Up migracji początkowej. Jeśli chcesz obniżyć istniejącą lokalną bazę danych do pustego stanu, najłatwiej jest to zrobić ręcznie, upuszczając bazę danych lub upuszczając wszystkie tabele. Po tym początkowym obniżeniu poziomu wszystkie obiekty bazy danych zostaną ponownie utworzone przy użyciu nazw domyślnych, więc ten problem nie zostanie ponownie przedstawiony.
  • Jeśli przyszłe zmiany w modelu wymagają zmiany lub porzucania jednego z obiektów bazy danych o nazwie inaczej, nie będzie to działać względem istniejącej lokalnej bazy danych — ponieważ nazwy nie będą zgodne z wartościami domyślnymi. Jednak będzie działać w odniesieniu do baz danych utworzonych od podstaw, ponieważ będą używać domyślnych nazw wybranych przez migracje. Możesz ręcznie wprowadzić te zmiany w lokalnej istniejącej bazie danych lub rozważyć ponowne utworzenie bazy danych przez migrację od podstaw — tak jak na innych maszynach.
  • Bazy danych utworzone przy użyciu metody Up migracji początkowej mogą się nieznacznie różnić od lokalnej bazy danych, ponieważ zostaną użyte obliczone domyślne nazwy indeksów i ograniczeń klucza obcego. Możesz również utworzyć indeksy dodatkowe, ponieważ migracje będą domyślnie tworzyć indeksy w kolumnach kluczy obcych — może to nie być tak w oryginalnej lokalnej bazie danych.

Nie wszystkie obiekty bazy danych są reprezentowane w modelu

Obiekty bazy danych, które nie są częścią modelu, nie będą obsługiwane przez migracje. Może to obejmować widoki, procedury składowane, uprawnienia, tabele, które nie są częścią modelu, dodatkowe indeksy itp.

Oto kilka przykładów, o których należy pamiętać:

  • Niezależnie od opcji wybranej w kroku 3, jeśli przyszłe zmiany w modelu wymagają zmiany lub porzucania tych dodatkowych obiektów Migracje nie będą wiedzieć, aby wprowadzić te zmiany. Jeśli na przykład usuniesz kolumnę z dodatkowym indeksem, migracje nie będą wiedzieć, aby usunąć indeks. Należy ręcznie dodać tę opcję do szkieletu Migracja.
  • Jeśli użyto opcji "Opcja druga: użyj pustej bazy danych jako punktu początkowego", te dodatkowe obiekty nie zostaną utworzone przez metodę Up migracji początkowej. Możesz zmodyfikować metody w górę i w dół, aby dbać o te dodatkowe obiekty, jeśli chcesz. W przypadku obiektów, które nie są natywnie obsługiwane w interfejsie API migracji , takich jak widoki, można użyć metody Sql , aby uruchomić nieprzetworzone środowisko SQL, aby je utworzyć/usunąć.