Jak włączyć migracje EF dla wielu kontekstów do oddzielnych baz danych?

122

Jak włączyć migracje Entity Framework 5 (wersja 5.0.0) dla wielu kontekstów bazy danych w tym samym projekcie, gdzie każdy kontekst odpowiada własnej bazie danych? Kiedy uruchamiam Enable-Migrationsw konsoli PM (Visual Studio 2012), pojawia się błąd z powodu wielu kontekstów:

PM> Enable-Migrations
More than one context type was found in the assembly 'DatabaseService'.
To enable migrations for DatabaseService.Models.Product1DbContext, use Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContext.
To enable migrations for DatabaseService.Models.Product2DbContext, use Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContext.

Jeśli uruchomię, Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContextnie mogę uruchomić, Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContextponieważ migracja już istnieje:Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.

aknuds1
źródło

Odpowiedzi:

126

Drugie wywołanie Enable-Migrations kończy się niepowodzeniem, ponieważ plik Configuration.cs już istnieje. Jeśli zmienisz nazwę tej klasy i pliku, powinieneś być w stanie uruchomić drugą opcję Enable-Migrations, która utworzy kolejny plik Configuration.cs.

Będziesz wtedy musiał określić, której konfiguracji chcesz użyć podczas aktualizacji baz danych.

Update-Database -ConfigurationTypeName MyRenamedConfiguration
ckal
źródło
1
Co to jest „MyRenamedConfiguration”?
Robert Noack
1
„MyRenamedConfiguration” to po prostu tekst zastępczy jako przykład. Mogłeś zmienić nazwę swojego oryginalnego pliku Configuration.cs na cokolwiek (np. FooBar, a następnie uruchomić Update-Database -ConfigurationTypeName FooBar).
ckal
3
skrócona forma: Update-Database -conf MyRenamedConfiguration
Peter Kerr
100

Oprócz tego, co @ckal zasugerował, że jest krytyczna aby każdy przemianowany Configuration.cs własną przestrzeń nazw. Jeśli tego nie zrobisz, EF spróbuje zastosować migracje do niewłaściwego kontekstu.

Oto konkretne kroki, które dobrze mi odpowiadają.

Jeśli migracje są pomieszane i chcesz utworzyć nową „linię bazową”:

  1. Usuń wszystkie istniejące pliki .cs w folderze Migracje
  2. W programie SSMS usuń tabelę systemową __MigrationHistory.

Tworzenie migracji początkowej:

  1. W konsoli Menedżera pakietów:

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. W Eksploratorze rozwiązań: Zmień nazwę Migrations.Configuration.cs na Migrations.ConfigurationA.cs. Powinno to automatycznie zmienić nazwę konstruktora, jeśli używasz programu Visual Studio. Upewnij się, że tak. Edytuj ConfigurationA.cs: Zmień przestrzeń nazw na NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. W Eksploratorze rozwiązań: Zmień nazwę Migrations.Configuration.cs na Migrations.ConfigurationB.cs. Ponownie upewnij się, że nazwa konstruktora również została odpowiednio zmieniona. Edytuj ConfigurationB.cs: Zmień przestrzeń nazw na NamespaceOfContext.Migrations.MigrationsB

  5. add-migration InitialBSchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB 
  6. Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
  7. add-migration InitialSurveySchema -IgnoreChanges -ConfigurationTypeName
    ConfigurationA -ProjectName ProjectContextIsInIfNotMainOne -StartupProjectName
    NameOfMainProject  -ConnectionStringName ContextA 
  8. Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA

Kroki tworzenia skryptów migracji w konsoli Menedżera pakietów:

  1. Uruchom polecenie

    Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA

    lub -

    Add-Migration MYMIGRATION -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB

    Można ponownie uruchomić to polecenie, dopóki zmiany nie zostaną zastosowane w bazie danych.

  2. Albo uruchom skrypty dla żądanej lokalnej bazy danych lub uruchom Update-Database bez -Script, aby zastosować lokalnie:

    Update-Database -ConfigurationTypeName ConfigurationA -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextA

    lub -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
Eric J.
źródło
Zmiana nr 4: Edytuj konfiguracjęA.cs -> Edytuj konfiguracjęB.cs
Brian Rizo
1
@Biran: Dzięki, że to zauważyłeś. Zredagowałem odpowiedź. Uwaga, możesz również samodzielnie edytować odpowiedzi. Ponieważ nie masz jeszcze 2000 reputacji, Twoje odpowiedzi trafiają do kolejki recenzji, ale ta kolejka jest zwykle przetwarzana szybko, więc Twoja zmiana prawdopodobnie została zatwierdzona w ciągu kilku minut.
Eric J.
5
DZIĘKUJĘ CI! Tego mi brakowało (przestrzeni nazw).
William M. Rawls
Może to pomóc, ponieważ początkowo nie było dla mnie jasne, jak zmienić nazwę w krokach 2 i 4 : Po zmianie nazwy pliku Configuration.cs na ConfigurationA.cs lub ConfigurationB.cs, zmiana nazwy powinna również skutkować utworzeniem klasy i jego konstruktor również zmienia nazwę na ConfigurationA lub ConfigurationB. Brak zmiany nazwy klasy spowoduje wyświetlenie komunikatu o błędzie po uruchomieniu polecenia add -igration - „Nie znaleziono typu konfiguracji migracji 'KonfiguracjaA' w zestawie '...'” - i tak, sformułowanie było złe, tak jak że w komunikatach błędów, które dostałem w VS2013 - LOL
Greg Barth
3
to mi pomogło! pełne instrukcje ze wszystkimi opcjami i zamówieniem. zaoszczędził mi godziny
elcool
82

Właśnie natknąłem się na ten sam problem i użyłem następującego rozwiązania (wszystko z konsoli Menedżera pakietów)

PM> Enable-Migrations -MigrationsDirectory "Migrations\ContextA" -ContextTypeName MyProject.Models.ContextA
PM> Enable-Migrations -MigrationsDirectory "Migrations\ContextB" -ContextTypeName MyProject.Models.ContextB

Spowoduje to utworzenie 2 oddzielnych folderów w folderze Migracje. Każdy będzie zawierał wygenerowany Configuration.csplik. Niestety nadal musisz zmienić nazwy tych Configuration.csplików, w przeciwnym razie pojawią się skargi dotyczące posiadania dwóch z nich. Zmieniłem nazwy moich plików na ConfigA.csiConfigB.cs

EDYTUJ : (dzięki uprzejmości Kevina McPheata) Pamiętaj, zmieniając nazwy plików Configuration.cs, zmień także nazwy klas i konstruktorów / EDYCJA

Dzięki tej strukturze możesz po prostu to zrobić

PM> Add-Migration -ConfigurationTypeName ConfigA
PM> Add-Migration -ConfigurationTypeName ConfigB

Który utworzy pliki kodu do migracji w folderze obok plików konfiguracyjnych (dobrze jest trzymać te pliki razem)

PM> Update-Database -ConfigurationTypeName ConfigA
PM> Update-Database -ConfigurationTypeName ConfigB

I wreszcie, te dwa polecenia zastosują poprawne migracje do odpowiednich baz danych.

EDYCJA 08 lutego 2016: Przeprowadziłem małe testy z EF7 w wersji 7.0.0-rc1-16348

Nie mogłem zmusić opcji -o | --outputDir do działania. Nadal dawałMicrosoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Wygląda jednak na to, że po dodaniu migracji po raz pierwszy jest ona dodawana do folderu Migrations, a kolejna migracja do innego kontekstu jest automatycznie umieszczana w podfolderze migracji.

ContextAWydaje się, że oryginalne nazwy naruszają niektóre konwencje nazewnictwa, więc używam teraz ContextAContexti ContextBContext. Używając tych nazw, możesz użyć następujących poleceń: (zwróć uwagę, że mój dnx nadal działa z konsoli menedżera pakietów i nie lubię otwierać osobnego okna CMD do wykonywania migracji)

PM> dnx ef migrations add Initial -c "ContextAContext"
PM> dnx ef migrations add Initial -c "ContextBContext"

Spowoduje to utworzenie migawki modelu i początkowej migracji w Migrationsfolderze dla ContextAContext. Utworzy folder o nazwie ContextBzawierający te pliki dlaContextBContext

Ręcznie dodałem ContextAfolder i przeniosłem pliki migracji z ContextAContextdo tego folderu. Następnie zmieniłem nazwę przestrzeni nazw w tych plikach (plik migawki, początkowa migracja i zauważam, że pod początkowym plikiem migracji znajduje się trzeci plik ... designer.cs). Musiałem dodać coś do .ContextAprzestrzeni nazw, a stamtąd framework ponownie obsługuje to automatycznie.

Użycie poniższych poleceń spowodowałoby utworzenie nowej migracji dla każdego kontekstu

PM>  dnx ef migrations add Update1 -c "ContextAContext"
PM>  dnx ef migrations add Update1 -c "ContextBContext"

a wygenerowane pliki są umieszczane w odpowiednich folderach.

bart s
źródło
5
najlepsze rozwiązanie, proste i przejrzysty folder.
Malick
2
To była odpowiedź, której potrzebowałem. Odpowiedzią była przestrzeń nazw dodana za pośrednictwem -MigrationsDirectory! Dziękuję Ci.
Crob
1
Ładne i czyste rozwiązanie. Dzięki.
Stefan Cebulak
4
1,5 roku później cieszę się, że mogę użyć własnego posta do skonfigurowania nowego projektu.
Bart s
1
Zauważ, że po uruchomieniu add-migrationwyświetli monit o podanie Name. To mnie trochę zrzuciło, ponieważ już dostarczałem ConfigurationTypeNamei byłem nieco zirytowany, kiedy to właśnie powiedział Name:. Ale oczywiście nazwa, której chce, to „czytelny dla człowieka” opis zmiany - np. AddedProductslub IncreaseLengthOfNameFields. W folderze Migracje otrzymasz to jako część nazwy klasy, aby łatwo było zobaczyć, co to jest. W efekcie Nameprzypomina to komentarz do zameldowania.
Simon_Weaver
7

Jeśli masz już „Konfiguracja” z wieloma migracjami i chcesz ją zachować bez zmian, zawsze możesz utworzyć nową klasę „Konfiguracja”, nadać jej inną nazwę, na przykład

class MyNewContextConfiguration : DbMigrationsConfiguration<MyNewDbContext>
{
   ...
}

następnie po prostu wydaj polecenie

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

a EF zorganizuje migrację bez problemów. Na koniec zaktualizuj swoją bazę danych, od teraz EF będzie narzekać, jeśli nie powiesz mu, którą konfigurację chcesz zaktualizować:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Gotowe.

Nie musisz zajmować się Enable-Migrations, ponieważ będzie narzekać, że „Konfiguracja” już istnieje, a zmiana nazwy istniejącej klasy konfiguracji spowoduje pojawienie się problemów w historii migracji.

Możesz kierować reklamy na różne bazy danych lub tę samą, wszystkie konfiguracje będą dobrze współdzielić tabelę __MigrationHistory.

Guillermo Ruffino
źródło
4

Aby zaktualizować typ bazy danych, korzystając z kodów w programie PowerShell ...

Update-Database -context EnrollmentAppContext

* jeśli istnieje więcej niż jedna baza danych, użyj tylko tego kodu, w innym przypadku nie jest to konieczne.

AHAMED AAQIB
źródło
4

Jeśli istnieje więcej baz danych, użyj następujących kodów w programie PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • „Starter” to nazwa migracji

  • „EnrollmentAppContext” to nazwa kontekstu mojej aplikacji

Możesz otworzyć PowerShell w VS, wykonując: Tools->NuGet Package Manager->Package Manager Console

AHAMED AAQIB
źródło
1
To mi pomogło. Dzięki! :)
noobprogrammer
0

EF 4,7 faktycznie daje wskazówkę podczas uruchamiania migracji włączania w wielu kontekstach.

W zestawie „Service.Domain” znaleziono więcej niż jeden typ kontekstu.

To enable migrations for 'Service.Domain.DatabaseContext.Context1', 
use Enable-Migrations -ContextTypeName Service.Domain.DatabaseContext.Context1.
To enable migrations for 'Service.Domain.DatabaseContext.Context2',
use Enable-Migrations -ContextTypeName Service.Domain.DatabaseContext.Context2.
Davit Mikuchadze
źródło