Comment activer les migrations EF pour plusieurs contextes pour séparer les bases de données?

122

Comment activer les migrations Entity Framework 5 (version 5.0.0) pour plusieurs contextes de base de données dans le même projet, où chaque contexte correspond à sa propre base de données? Lorsque j'exécute Enable-Migrationsdans la console PM (Visual Studio 2012), il y a une erreur en raison de l'existence de plusieurs contextes:

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.

Si je cours, Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContextje ne suis pas autorisé à courir Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContextcar une migration existe déjà:Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.

aknuds1
la source
4
Jetez un œil à Data Points - EF6 Code First Migrations for Multiple Models par Julie Lerman
Développeur Marius Žilėnas

Réponses:

126

Le deuxième appel à Enable-Migrations échoue car le fichier Configuration.cs existe déjà. Si vous renommez cette classe et ce fichier, vous devriez être en mesure d'exécuter ce 2nd Enable-Migrations, ce qui créera un autre Configuration.cs.

Vous devrez ensuite spécifier la configuration que vous souhaitez utiliser lors de la mise à jour des bases de données.

Update-Database -ConfigurationTypeName MyRenamedConfiguration
ckal
la source
1
Qu'est-ce que "MyRenamedConfiguration"?
Robert Noack
1
"MyRenamedConfiguration" est juste un texte d'espace réservé à titre d'exemple. Vous pourriez avoir renommé votre Configuration.cs d'origine en n'importe quoi, (par exemple FooBar, puis exécutez Update-Database -ConfigurationTypeName FooBar).
ckal
3
forme abrégée: Update-Database -conf MyRenamedConfiguration
Peter Kerr
100

En plus de ce que @ckal a suggéré, il est essentiel de donner à chaque Configuration.cs renommée son propre espace de noms. Si vous ne le faites pas, EF tentera d'appliquer les migrations au mauvais contexte.

Voici les étapes spécifiques qui fonctionnent bien pour moi.

Si les migrations sont interrompues et que vous souhaitez créer une nouvelle «ligne de base»:

  1. Supprimer tous les fichiers .cs existants dans le dossier Migrations
  2. Dans SSMS, supprimez la table système __MigrationHistory.

Création de la migration initiale:

  1. Dans la console du gestionnaire de package:

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. Dans l'Explorateur de solutions: renommez Migrations.Configuration.cs en Migrations.ConfigurationA.cs. Cela devrait automatiquement renommer le constructeur si vous utilisez Visual Studio. Assurez-vous que c'est le cas. Modifier ConfigurationA.cs: remplacez l'espace de noms par NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. Dans l'Explorateur de solutions: renommez Migrations.Configuration.cs en Migrations.ConfigurationB.cs. Encore une fois, assurez-vous que le constructeur est également renommé de manière appropriée. Modifier la configurationB.cs: remplacez l'espace de noms par 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

Étapes pour créer des scripts de migration dans la console du gestionnaire de package:

  1. Exécuter la commande

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

    ou -

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

    Il est possible de réexécuter cette commande jusqu'à ce que les modifications soient appliquées à la base de données.

  2. Exécutez les scripts sur la base de données locale souhaitée ou exécutez Update-Database sans -Script pour appliquer localement:

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

    ou -

    Update-Database -ConfigurationTypeName ConfigurationB -ProjectName
    ProjectContextIsInIfNotMainOne -StartupProjectName NameOfMainProject
    -ConnectionStringName ContextB
Eric J.
la source
# 4 changement: Modifier ConfigurationA.cs -> Modifier ConfigurationB.cs
Brian Rizo
1
@Biran: Merci d'avoir remarqué cela. J'ai édité la réponse. Notez que vous pouvez également modifier les réponses vous-même. Comme vous n'avez pas encore 2000 points de réputation, vos réponses dans une file d'attente de révision, mais cette file d'attente est généralement traitée rapidement, donc votre modification aurait probablement été approuvée en quelques minutes.
Eric J.
5
MERCI! C'était ce qui me manquait (les espaces de noms).
William M. Rawls
Cela peut aider car je ne savais pas comment faire le changement de nom aux étapes 2 et 4 au départ: lorsque vous renommez le fichier Configuration.cs en ConfigurationA.cs ou ConfigurationB.cs, le changement de nom devrait également entraîner la classe et son constructeur est également renommé en ConfigurationA ou ConfigurationB. Le fait de ne pas renommer la classe provoquera un message d'erreur lorsque vous exécutez la commande add-migration - "Le type de configuration des migrations 'ConfigurationA' n'a pas été trouvé dans l'assembly '...'" - et oui, le libellé était mauvais, tout comme que dans les messages d'erreur que j'ai reçus dans VS2013 - LOL
Greg Barth
3
cela m'a aidé! instructions complètes avec toutes les options et commande. m'a sauvé des heures
elcool
82

Je viens de tomber sur le même problème et j'ai utilisé la solution suivante (tout à partir de la console du gestionnaire de package)

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

Cela créera 2 dossiers séparés dans le dossier Migrations. Chacun contiendra le Configuration.csfichier généré . Malheureusement, vous devez toujours renommer ces Configuration.csfichiers, sinon il y aura des plaintes à propos de deux d'entre eux. J'ai renommé mes fichiers en ConfigA.csetConfigB.cs

EDIT : (avec la permission de Kevin McPheat) N'oubliez pas lorsque vous renommez les fichiers Configuration.cs, renommez également les noms de classe et les constructeurs / EDIT

Avec cette structure, vous pouvez simplement faire

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

Ce qui créera les fichiers de code pour la migration dans le dossier à côté des fichiers de configuration (c'est bien de garder ces fichiers ensemble)

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

Enfin, ces deux commandes appliqueront les migrations correctes à leurs bases de données correspondantes.

EDIT 08 février 2016: J'ai fait un petit test avec EF7 version 7.0.0-rc1-16348

Je n'ai pas pu faire fonctionner l'option -o | --outputDir. Il a continué à donnerMicrosoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Cependant, il semble que la première fois qu'une migration est ajoutée, elle est ajoutée dans le dossier Migrations, et une migration ultérieure pour un autre contexte est automatiquement placée dans un sous-dossier de migrations.

Les noms originaux ContextAsemblent enfreindre certaines conventions de dénomination, j'utilise maintenant ContextAContextet ContextBContext. En utilisant ces noms, vous pouvez utiliser les commandes suivantes: (notez que mon dnx fonctionne toujours à partir de la console du gestionnaire de packages et que je n'aime pas ouvrir une fenêtre CMD séparée pour faire des migrations)

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

Cela créera un instantané du modèle et une migration initiale dans le Migrationsdossier pour ContextAContext. Il créera un dossier nommé ContextBcontenant ces fichiers pourContextBContext

J'ai ajouté manuellement un ContextAdossier et déplacé les fichiers de migration depuis ContextAContextce dossier. Ensuite, j'ai renommé l'espace de noms à l'intérieur de ces fichiers (fichier instantané, migration initiale et note qu'il y a un troisième fichier sous le fichier de migration initial ... designer.cs). J'ai dû ajouter .ContextAà l'espace de noms, et à partir de là, le framework le gère à nouveau automatiquement.

L'utilisation des commandes suivantes créerait une nouvelle migration pour chaque contexte

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

et les fichiers générés sont placés dans les bons dossiers.

bart s
la source
5
la meilleure solution, simple et nous gardons un dossier clair.
Malick
2
C'était la réponse dont j'avais besoin. L'espace de noms ajouté via -MigrationsDirectory était la réponse! Je vous remercie.
Crob
1
Solution agréable et propre. Merci.
Stefan Cebulak
4
1,5 an plus tard, je suis heureux de pouvoir utiliser mon propre message pour mettre en place un nouveau projet.
bart s
1
Notez que lorsque vous exécutez, add-migrationil vous demandera Name. Cela m'a légèrement déconcerté car je fournissais déjà ConfigurationTypeNameet j'ai été légèrement ennuyé quand il vient de le dire Name:. Mais bien sûr, le nom qu'il veut est la description «lisible par l'homme» du changement - par exemple. AddedProductsou IncreaseLengthOfNameFields. Dans le dossier Migrations, vous l'obtiendrez dans le cadre du nom de la classe afin qu'il soit facile de voir ce qui est quoi. Donc, en fait, Namec'est un peu comme un commentaire d'enregistrement.
Simon_Weaver
7

Si vous avez déjà une "Configuration" avec de nombreuses migrations et que vous souhaitez la conserver telle quelle, vous pouvez toujours créer une nouvelle classe "Configuration", lui donner un autre nom, comme

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

alors émettez simplement la commande

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

et EF échafaudera la migration sans problème. Enfin, mettez à jour votre base de données, à partir de maintenant, EF se plaindra si vous ne lui dites pas quelle configuration vous souhaitez mettre à jour:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Terminé.

Vous n'avez pas besoin de traiter Enable-Migrations car il se plaindra que "Configuration" existe déjà, et renommer votre classe de configuration existante entraînera des problèmes dans l'historique de migration.

Vous pouvez cibler différentes bases de données, ou la même, toutes les configurations partageront bien la table __MigrationHistory.

Guillermo Ruffino
la source
4

Si plusieurs bases de données existent, utilisez les codes suivants dans PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • «Starter» est le nom de la migration

  • 'EnrollmentAppContext' est le nom de mon contexte d'application

Vous pouvez ouvrir PowerShell dans VS en faisant: Tools->NuGet Package Manager->Package Manager Console

AHAMED AAQIB
la source
1
Cela m'a aidé. Merci! :)
noobprogrammer
3

Pour mettre à jour le type de base de données en suivant les codes dans PowerShell ...

Update-Database -context EnrollmentAppContext

* s'il existe plus d'une base de données, utilisez uniquement ces codes, sinon pas nécessaire.

AHAMED AAQIB
la source
0

EF 4.7 donne en fait un indice lorsque vous exécutez Enable-migrations à plusieurs contextes.

Plus d'un type de contexte a été trouvé dans l'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.
Davit Mikuchadze
la source