Come si abilitano le migrazioni EF per più contesti per separare i database?


122

Come si abilitano le migrazioni di Entity Framework 5 (versione 5.0.0) per più contesti database nello stesso progetto, dove ogni contesto corrisponde al proprio database? Quando eseguo Enable-Migrationsnella console PM (Visual Studio 2012), si verifica un errore a causa della presenza di più contesti:

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.

Se corro Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContextnon posso eseguire Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContextperché esiste già una migrazione:Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.


Risposte:


126

La seconda chiamata a Enable-Migrations non riesce perché il file Configuration.cs esiste già. Se rinomini quella classe e quel file, dovresti essere in grado di eseguire quel 2nd Enable-Migrations, che creerà un altro Configuration.cs.

Sarà quindi necessario specificare quale configurazione si desidera utilizzare durante l'aggiornamento dei database.

Update-Database -ConfigurationTypeName MyRenamedConfiguration

1
Che cos'è "MyRenamedConfiguration"?
Robert Noack

1
"MyRenamedConfiguration" è solo un testo segnaposto come esempio. Avresti potuto rinominare il tuo Configuration.cs originale in qualsiasi cosa, (ad esempio FooBar, quindi eseguire Update-Database -ConfigurationTypeName FooBar).
ckal

3
abbreviare la forma: Update-Database -conf MyRenamedConfiguration
Peter Kerr

100

Oltre a quanto suggerito da @ckal, è fondamentale assegnare a ogni Configuration.cs rinominato il proprio spazio dei nomi. In caso contrario, EF tenterà di applicare le migrazioni al contesto sbagliato.

Ecco i passaggi specifici che funzionano bene per me.

Se le migrazioni sono incasinate e desideri creare una nuova "linea di base":

  1. Elimina tutti i file .cs esistenti nella cartella Migrations
  2. In SSMS, elimina la tabella di sistema __MigrationHistory.

Creazione della migrazione iniziale:

  1. Nella console di Gestione pacchetti:

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. In Esplora soluzioni: rinominare Migrations.Configuration.cs in Migrations.ConfigurationA.cs. Questo dovrebbe rinominare automaticamente il costruttore se si usa Visual Studio. Assicurati che lo faccia. Modifica ConfigurationA.cs: modifica lo spazio dei nomi in NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. In Esplora soluzioni: rinominare Migrations.Configuration.cs in Migrations.ConfigurationB.cs. Di nuovo, assicurati che anche il costruttore sia rinominato in modo appropriato. Modifica ConfigurationB.cs: modifica lo spazio dei nomi in 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

Passaggi per creare script di migrazione nella console di Gestione pacchetti:

  1. Esegui comando

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

    o -

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

    È possibile eseguire nuovamente questo comando fino a quando le modifiche non vengono applicate al database.

  2. Eseguire gli script sul database locale desiderato o eseguire Update-Database senza -Script da applicare localmente:

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

    o -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB

# 4 modifica: Modifica configurazioneA.cs -> Modifica configurazioneB.cs
Brian Rizo

1
@ Biran: Grazie per averlo notato. Ho modificato la risposta. Nota, puoi modificare le risposte anche tu. Dal momento che non hai ancora 2000 reputazione, le tue risposte a in una coda di revisione, ma quella coda di solito viene elaborata rapidamente, quindi la tua modifica sarebbe stata approvata probabilmente entro pochi minuti.
Eric J.

5
GRAZIE! Questo era quello che mi mancava (gli spazi dei nomi).
William M. Rawls

Questo può aiutare perché non mi era chiaro come eseguire la ridenominazione nei passaggi 2 e 4 inizialmente: quando si rinomina il file Configuration.cs in ConfigurationA.cs o ConfigurationB.cs, la ridenominazione dovrebbe comportare anche la classe e anche il suo costruttore viene rinominato in ConfigurationA o ConfigurationB. L'impossibilità di rinominare la classe causerà un messaggio di errore quando si esegue il comando add-migration - "Il tipo di configurazione delle migrazioni 'ConfigurationA' non è stato trovato nell'assembly '...'" - e sì, la dicitura era pessima proprio come quello nei messaggi di errore che ho ricevuto in VS2013 - LOL
Greg Barth

3
questo mi ha aiutato! istruzioni complete con tutte le opzioni e l'ordine. mi ha fatto risparmiare ore
elcool

82

Mi sono appena imbattuto nello stesso problema e ho usato la seguente soluzione (tutto da Package Manager Console)

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

Questo creerà 2 cartelle separate nella cartella Migrations. Ciascuno conterrà il Configuration.csfile generato . Sfortunatamente devi ancora rinominare quei Configuration.csfile altrimenti ci saranno dei reclami per averne due. Ho rinominato i miei file in ConfigA.cseConfigB.cs

EDIT : (per gentile concessione di Kevin McPheat) Ricorda quando rinomini i file Configuration.cs, rinomina anche i nomi delle classi e dei costruttori / EDIT

Con questa struttura puoi semplicemente fare

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

Che creerà i file di codice per la migrazione all'interno della cartella accanto ai file di configurazione (è bello tenere insieme quei file)

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

E, ultimo ma non meno importante, questi due comandi applicheranno le migrazioni corrette ai database corrispondenti.

EDIT 08 febbraio 2016: ho fatto un piccolo test con EF7 versione 7.0.0-rc1-16348

Non sono riuscito a far funzionare l'opzione -o | --outputDir. Ha continuato a dareMicrosoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Tuttavia sembra che la prima volta che viene aggiunta una migrazione, questa viene aggiunta alla cartella Migrations e una successiva migrazione per un altro contesto viene automaticamente inserita in una sottocartella delle migrazioni.

I nomi originali ContextAsembrano violare alcune convenzioni di denominazione, quindi ora uso ContextAContexte ContextBContext. Usando questi nomi potresti usare i seguenti comandi: (nota che il mio dnx funziona ancora dalla console del gestore pacchetti e non mi piace aprire una finestra CMD separata per fare le migrazioni)

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

Questo creerà un'istantanea del modello e una migrazione iniziale nella Migrationscartella per ContextAContext. Creerà una cartella denominata ContextBcontenente questi file perContextBContext

Ho aggiunto manualmente una ContextAcartella e ho spostato i file di migrazione da ContextAContextin quella cartella. Quindi ho rinominato lo spazio dei nomi all'interno di quei file (file snapshot, migrazione iniziale e nota che c'è un terzo file sotto il file di migrazione iniziale ... designer.cs). Ho dovuto aggiungere .ContextAallo spazio dei nomi e da lì il framework lo gestisce di nuovo automaticamente.

L'utilizzo dei seguenti comandi creerebbe una nuova migrazione per ogni contesto

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

ei file generati vengono inseriti nelle cartelle corrette.


5
la soluzione migliore, semplice e teniamo una cartella chiara.
Malick

2
Questa era la risposta di cui avevo bisogno. Lo spazio dei nomi aggiunto tramite -MigrationsDirectory era la risposta! Grazie.
Crob

1
Soluzione bella e pulita. Grazie.
Stefan Cebulak

4
Un anno e mezzo dopo, sono felice di poter usare il mio post per impostare un nuovo progetto.
bart s

1
Nota quando lo esegui add-migrationti chiederà Name. Questo mi ha sconcertato un po 'dal momento che stavo già fornendo ConfigurationTypeNamee si è leggermente infastidito quando ha appena detto Name:. Ma ovviamente il Nome che vuole è la descrizione "leggibile dall'uomo" del cambiamento - es. AddedProductso IncreaseLengthOfNameFields. Nella cartella Migrations lo otterrai come parte del nome della classe, quindi è facile vedere cosa è cosa. Quindi in effetti Nameè una specie di commento per il check-in.
Simon_Weaver

7

Nel caso tu abbia già una "Configurazione" con molte migrazioni e desideri mantenerla così com'è, puoi sempre creare una nuova classe "Configurazione", assegnandole un altro nome, come

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

quindi emetti semplicemente il comando

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

ed EF imposterà la migrazione senza problemi. Infine aggiorna il tuo database, d'ora in poi EF si lamenterà se non gli dici quale configurazione vuoi aggiornare:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Fatto.

Non è necessario occuparsi di Enable-Migrations in quanto si lamenterà che "Configurazione" esiste già e rinominare la classe di configurazione esistente porterà problemi alla cronologia della migrazione.

Puoi scegliere come target database diversi o lo stesso, tutte le configurazioni condivideranno bene la tabella __MigrationHistory.


4

Se esistono più database, utilizzare i seguenti codici in PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • "Starter" è il nome della migrazione

  • "EnrollmentAppContext" è il nome del contesto della mia app

Puoi aprire PowerShell in VS eseguendo: Tools->NuGet Package Manager->Package Manager Console


1
Questo mi ha aiutato. Grazie! :)
noobprogrammer

3

Per aggiornare il tipo di database seguendo i codici in PowerShell ...

Update-Database -context EnrollmentAppContext

* se esistono più database utilizzare solo questo codice, altrimenti non necessario ..


0

EF 4.7 fornisce effettivamente un suggerimento quando si esegue Enable-migrations in più contesti.

È stato trovato più di un tipo di contesto nell'assembly "Service.Domain".

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.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.