Jak zarządzać MIGRACJAMI W projekcie z wieloma gałęziami?

Mam ASP.NET projekt MVC3 wykorzystujący Entity Framework 4.3 z podejściem code-first. Używam migracji, aby utrzymać aktualną bazę danych.

Projekt jest pod kontrolą źródeł i mam kilka gałęzi. Właśnie zdałem sobie sprawę, że będzie problem, kiedy chcę połączyć jedną z moich gałęzi z mistrzem. Ponieważ utworzyłem migracyjne pliki w obu gałęziach, migracje będą nakładać się podczas łączenia, co prawdopodobnie spowoduje konflikty.

Jest czy jest dobry sposób na zarządzanie migracjami w projekcie z wieloma gałęziami?

Update

Jednym ze sposobów byłoby scalenie, a następnie usunięcie wszystkich plików migracji utworzonych, gdy gałęzie były oddzielne, a następnie utworzenie jednego nowego pliku migracji, który przechowuje wszystkie zmiany od czasu utworzenia gałęzi do ponownego scalenia. Działa to w środowisku deweloperskim, gdzie można zrzut bazy danych i ponownie zbudować ją ze wszystkimi plikami migracji. Problemem byłoby wtedy środowisko życia. Ponieważ nie można cofnąć czasu utworzenia gałęzi bez ryzyka utraty danych, podczas próby użycia nowego pliku migracji do aktualizacji aktywnej bazy danych pojawi się konflikt.

Author: Shaul Behr, 2012-05-11

7 answers

Myślę, że przyjęta odpowiedź jest niepoprawna. Istnieje znacznie lepsze rozwiązanie do obsługi konfliktów merge migration entity Framework na podobne pytanie.

Wszystko, co musisz zrobić po scaleniu, to zmienić rusztowanie metadanych migracji w docelowej gałęzi. Oznacza to, że nie zmieniasz kodu góra / dół, tylko stan w pliku resx.

add-migration [the_migration_to_rescaffold_metadata_for]

Ta procedura zakończy się niepowodzeniem, jeśli inna migracja podczas scalania zmieni bazę danych w taki sposób, że migracja nie jest już wykonalna lub daje nieoczekiwany wynik. Biorąc to pod uwagę-wierzę, że jest to bardzo rzadki przypadek, ponieważ większość migracji powinna być automatycznie generowana, a przynajmniej nie zależeć od innych tabel, które nie są zmieniane również w samej migracji. Bardzo drobny problem, ale trzeba mieć go na uwadze.

Jednym z takich przypadków może być fxp (nie mogłem wymyślić lepszego przykładu)

  • Kolumna foo jest int, a wiersze zawierają [0, 1, 2]

  • Migracja A z rozgałęź zmianę foo na boolean (0 stanie się false automatycznie i > 0 stanie się prawdą)

  • Migracja B z gałęzi B zmiana foo na string. Oczekuje, że będzie to int, ale jest to logiczny, migracja jednak się powiedzie. Dane zostaną utracone, ponieważ po utworzeniu migracji B wiersze będą zawierać ["0", "1", "2"]. Podczas migracji zmienionej kolumny do logicznego (i zrobił to pomyślnie i z oczekiwanym wynikiem) wiersze będą teraz zawierać ["0", "1", "1"] Zamiast i migracja B będzie miał inny efekt końcowy niż ten, który zaobserwowano w gałęzi B.

Jest prawdopodobnie więcej przypadków, w których coś mogłoby pójść nie tak z rozwiązaniem. Ale jeśli migracje w górę / w dół kod nie jest zależny od rzeczy zmienionych przez inną migrację w połączeniu powinno działać dobrze, aby po prostu zaktualizować metadane w migracjach.

 16
Author: oldwizard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:10

Scalanie migracji jest IMHO zadaniem ręcznym. Część kodu migracji jest generowana automatycznie i zwykle nie łączymy wygenerowanego automatycznie kodu - zamiast tego uruchamiamy ponownie autogenerację po scaleniu.

Do ADO.NET zespół podaje pewne zalecenia, które kieruję się prostą zasadą:

  • przed wykonaniem połączenia Przywróć główną bazę danych do wersji używanej przed rozgałęzieniem
  • Połącz swoje gałęzie
  • Wyklucz klasy migracji utworzone po rozgałęzieniu z scalonych assembly
  • Dodaj nową migrację dla Scalonej bazy kodu, która przeniesie Twoją bazę danych w stan przed rozgałęzieniem do stanu po połączeniu gałęzi
  • jeśli wykluczone klasy migracji zawierają pewne modyfikacje, połącz je z nową klasą migracji
  • Uruchom migrację, aby przenieść bazę danych do bieżącej połączonej wersji

Jeśli Twoje gałęzie zawierały wiele kroków migracji (wersja), stracisz je i skończysz z dwiema wersjami-przed rozgałęzienia i po połączeniu.

Edit:

Nie będzie działać w środowisku na żywo. Problemem byłby tu sam proces rozwoju. Jeśli masz środowisko live, powinieneś zachować jego gałąź nietkniętą (poza drobnymi poprawkami błędów). Jeśli kontynuujesz rozwój w tej gałęzi z wdrożeniem produkcyjnym i w tym samym czasie zbudujesz inną wersję w oddzielnej gałęzi bez ciągłej integracji (=ciągłe scalanie zmian z powrotem do głównej gałęzi, aby zintegrować nową rozwój z główną bazą kodu) masz duży problem. Myślę, że migracje w ogóle sobie z tym nie poradzą.

Jedyną opcją w takim przypadku byłoby prawdopodobnie usunięcie wszystkich migracji z scalonego rozwiązania i usunięcie tabeli MigrationHistory z bazy danych. Następnie możesz ponownie włączyć migracje w projekcie i dodać migrację początkową, aby użyć bieżącej bazy danych jako punktu wyjścia = nie ma powrotu do poprzedniej wersji, ponieważ nie będzie informacji o poprzednich migracjach.

 13
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-12 12:46:22

Edit: mój kolega odkrył łatwiejsze z tym, zostawiłem oryginalną odpowiedź na dole dla kompletności.

(bardzo ważne) migracje w środowisku live nie mogą kolidować z migracjami w bieżącej gałęzi, w przeciwnym razie musisz ponowić wszystkie migracje i ręcznie rozwiązać konflikty zmian w modelu danych.

  1. Przywróć bazę programistyczną za pomocą danych środowiska NA ŻYWO
  2. Uruchom update-database, powinien uruchomić migracje z Twojej gałęzi i Skarga na " nie można zaktualizować bazy danych, aby pasowały do bieżącego modelu bla bla..'
  3. uruchom add-migration MergeBranchBToMaster -ignoreChanges, spowoduje to utworzenie pustej migracji.
  4. run update-database again
  5. push your changes

Magia w kroku 3 zasadniczo mówi EF, aby zamknął się o niedopasowanych modelach, dlatego upewnij się, że migracje nie są sprzeczne z tymi w środowisku na żywo. Jeśli tak się stanie, zawsze możesz utworzyć skrypty SQL do wypychania brakujących migracji (co jest w rzeczywistości preferowanym metoda).

Oryginalna Odpowiedź

Znalazłem dość proste rozwiązanie oparte na odpowiedzi @ Ladislav Mrnka. Będzie to działać w środowisku live [1], Musisz tylko uważać, aby nie zmieniać wdrożonych migracji.

  1. Przed scaleniem zapoznaj się z dodaną migracją (MyMigration), i jego poprzedniej migracji (BaseMigration)

  2. Merge branches in git

  3. Otwórz konsolę menedżera pakietów i uruchom: UPDATE-DATABASE-TargetMigration:BaseMigration. Spowoduje to przywrócenie bazy danych do stanu przed zastosowaniem którejkolwiek z konfliktowych migracji

  4. Usuń swoją lokalną migrację (MyMigration)

  5. Uruchom: UPDATE-DATABASE. Będzie to miało zastosowanie do wszystkich nowszych migracji wykonanych w innych gałęziach.

  6. Run: ADD-MIGRATION MyMigration. Spowoduje to ponowne wygenerowanie Twojej lokalnej migracji na podstawie aktualnego stanu bazy danych, jak np. git-rebase.

  7. Bieg: AKTUALIZACJA-BAZA DANYCH. Aktualizuj bazę danych za pomocą migracji lokalnej.

Działa to również w przypadku wielu lokalnych migracji, ale połączy je wszystkie w jedną.

[1] pracując ze środowiskiem live, mam na myśli, że wygenerowana migracja może być zastosowana do środowiska live, które może mieć już zastosowane migracje niektórych / wszystkich innych gałęzi. Same kroki są wyłącznie w celu rozwoju.

 13
Author: Bill Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-27 13:23:32

Rowan Miller nakręcił świetny film na ten temat na kanale 9: migracje-środowiska zespołowe . Odnosi się ona do ram podmiotowych 6.

Opisuje scenariusz, w którym pierwszy programista A i B pracują nad tym samym modelem, a pierwszy sprawdza. Teraz programista B musi poradzić sobie z problemami, które ma, gdy dostanie najnowszą wersję od A.

Jest to zasadniczo to samo, jak konflikty między różnymi gałęziami, ponieważ ogólnym problemem jest scalanie migracji zmiany zrobiły to w tym samym czasie, ale skutecznie posiadające inny stan źródłowy modelu.

Rozwiązaniem jest:

  • podczas rozwiązywania konfliktów systemu kontroli wersji, programista B musi zaakceptować zarówno zmiany od siebie, jak i dewelopera A.
  • polecenie UpdateDatabase programisty B nadal nie powiedzie się w tym czasie(komunikat o błędzie: " nie można zaktualizować bazy danych, aby pasowała do bieżącego modelu, ponieważ są oczekujące zmiany...")
  • programista B musi Utwórz "pustą migrację" używając opcji IgnoreChanges:

Add-Migration NameOfMigration -IgnoreChanges

Wtedy polecenie UpdateDatabase powiedzie się.


Źródło problemu

Źródłem błędu występującego podczas aktualizacji bazy danych jest to, że EF przechowuje migawkę modelu, do którego odnosi się migracja w pliku resx w pliku migracji.

W tym przypadku programiści B migawka "bieżącego modelu" nie jest poprawna po pobraniu / połączeniu zmian dokonanych przez programista A.

 8
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 09:16:45

Przemyślałem to i mam nadzieję, że przyczynię się do różnych opinii i praktyk przedstawionych tutaj.

Zastanów się, co w rzeczywistości reprezentują Twoje lokalne migracje. Pracując lokalnie z dev bazą danych, używam migracji do aktualizacji bazy danych w najwygodniejszy możliwy sposób przy dodawaniu kolumn itp. do tabel, dodawaniu nowych encji itp.

Więc, add-Migration sprawdza Mój bieżący model (nazwijmy go modelem b) przeciwko Mój poprzedni model (model A) i generuje migrację z a = > b w bazie danych.

Dla mnie bardzo mało sensowne jest łączenie moich migracji z innymi migracjami, Jeśli każdy rzeczywiście ma swoją własną bazę danych i istnieje jakiś rodzaj serwerów baz danych stage / test / dev / production w organizacji. Wszystko zależy od tego, jak zespół go skonfigurował, ale sensowne jest izolowanie się od zmian, które wprowadzają inni ludzie, jeśli chcesz naprawdę pracować w sposób rozproszony.

Cóż, jeśli pracujesz rozproszony i mieć jakiś podmiot, osoba, na przykład, że pracujesz na. Z jakiegoś powodu wiele innych osób również nad tym pracuje. Tak więc dodajesz i usuwasz właściwości osoby w zależności od potrzeb twojej konkretnej historii w sprincie (wszyscy pracujemy zwinnie, prawda?), np. numer ubezpieczenia społecznego, który najpierw przerobiłeś na liczbę całkowitą, bo nie jesteś taki jasny, a potem na ciąg itp.

Dodajesz FirstName i Ostatnie imię.

Jesteś skończony i masz dziesięć dziwnych migracji w górę i w dół (prawdopodobnie usunąłeś niektóre z nich podczas pracy, ponieważ były po prostu gówniane) i pobierasz kilka zmian z centralnego repo Git. Wow. Twój kolega Bob też potrzebował jakichś nazwisk, może powinniście ze sobą porozmawiać?

W każdym razie, dodał NameFirst i NameLast, tak myślę... więc czym się zajmujesz? Cóż, łączysz się, refaktor, zmieniasz, żeby miało bardziej rozsądne nazwy... jak FirstName i LastName, uruchamiasz swoje sprawdź jego kod, a potem wciśnij go do środka.

Ale co z migracjami? Cóż, teraz byłby czas, aby migracja przenosząca centralny repo, a dokładniej gałąź "test", zawierała ładną małą migrację z jej modelu a = > Modelu b. ta migracja będzie jedną i tylko jedną migracją, a nie dziesięcioma dziwnymi.

Widzisz do czego zmierzam? Pracujemy z nice little pocos i porównania z nich stanowią rzeczywisty migracje. Nie powinniśmy więc w ogóle łączyć migracji, moim zdaniem powinniśmy mieć migracje-per-branch czy coś w tym stylu.

Czy w ogóle musimy utworzyć migrację w gałęzi po scaleniu? Tak, jeśli ta baza danych jest aktualizowana automatycznie, musimy.

Muszę popracować jeszcze trochę, to przynajmniej moje przemyślenia na ten temat.

 4
Author: LavaEater,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-12 09:54:03

Rozważ użycie innej biblioteki migracji, która nie powoduje tych konfliktów, np. FluentMigrator lub Migrator.NET.

Nie sądzę, aby migracje EF były gotowe do ogólnego użytku z gałęziami i połączeniami - to dużo pracy i zbyt łatwe do popełniania paskudnych błędów.

 2
Author: Eamon Nerbonne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-19 13:51:13

Myślę, że to, co mówi @ LavaEater, ma sens. Wdrażam strategię rozgałęzienia (Development, Main, Release) i dostosowuję ją do środowisk w procesie rozwoju, kontroli jakości i Wydania.

  • dział rozwoju-Rozwój lokalny
  • W przypadku, gdy nie jest to możliwe, możesz skorzystać z usługi Microsoft Azure SQL, aby uzyskać dostęp do usługi Microsoft Azure SQL SQL SQL SQL SQL SQL SQL SQL SQL SQL SQL SQL]}
  • Release branch-Scalanie zmian ze środowiska głównego i wdrożenia do środowiska produkcyjnego (inna witryna Azure i baza danych SQL)

Zetknąłem się z omawianym powyżej problemem i moim zdaniem komplikacje związane z migracjami i potencjalnymi obejściami wprowadzają wiele ryzyka w proces uwalniania. Wykonywanie niezależnych migracji w Development, Main i Release skutecznie oznacza, że schemat, który zawarłem w kompilacji w Dev, nie jest schematem, który przechodzi do QA na Staging, a schemat, który podpisuje QA na Staging, nie jest schematem, który jest wdrożony do życia (chyba, że podążam za jednym z sugerowanych rozwiązań, które jestem pewien, że zadziała, ale może być podatny na błędy).

Do echo @LavaEater-jaka jest realna korzyść z kodu EF? Osobiście uważam, że jest to łatwość, z jaką mogę wygenerować schemat z kodu (i potencjalnie dostosować automatycznie generowane migracje, jeśli chcę). Następnie migracje są komplikacją tego, co powinno być prostym procesem wdrażania.

Moim obecnym myśleniem jest użycie najpierw kodu aby wygenerować migracje w rozwoju, a następnie: -

  • Opcja A) - Use Update-Database-script to script up the schema changes and put them under source control. Nadal istnieje pewien potencjał konfliktów, jeśli 2 osoby zmieniają ten sam model, ale myślę, że łatwiej jest zarządzać.

  • Opcja B) - użyj czegoś takiego jak SQL Compare do generowania skryptów zmiany schematu. Jest to potencjalnie bardziej elastyczne i przejrzyste, jak lubię zobaczyć dokładnie, co schemat zmiany, które stosuję w Bazie Danych produkcji (nazwij mnie paranoikiem).

Czy coś przeoczyłem? Domyślam się, że będzie jakaś konfiguracja do zrobienia, aby wyłączyć pierwsze migracje kodu w gałęziach Main i Release (przy założeniu, że DB będzie tworzone i aktualizowane przez skrypty). Poza tym wydaje się to bezpiecznym rozwiązaniem, ale ceniłbym drugą opinię.

 0
Author: Liam Weston,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-08 14:36:11