¿Cómo habilito las migraciones de EF para múltiples contextos para separar bases de datos?


122

¿Cómo habilito las migraciones de Entity Framework 5 (versión 5.0.0) para múltiples contextos de base de datos en el mismo proyecto, donde cada contexto corresponde a su propia base de datos? Cuando ejecuto Enable-Migrationsen la consola de PM (Visual Studio 2012), hay un error debido a que existen múltiples contextos:

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 ejecuto, Enable-Migrations -ContextTypeName DatabaseService.Models.Product1DbContextno puedo ejecutar Enable-Migrations -ContextTypeName DatabaseService.Models.Product2DbContextporque ya existe una migración:Migrations have already been enabled in project 'DatabaseService'. To overwrite the existing migrations configuration, use the -Force parameter.


Respuestas:


126

La segunda llamada a Enable-Migrations falla porque el archivo Configuration.cs ya existe. Si cambia el nombre de esa clase y archivo, debería poder ejecutar ese segundo Enable-Migrations, que creará otro Configuration.cs.

Luego deberá especificar qué configuración desea utilizar al actualizar las bases de datos.

Update-Database -ConfigurationTypeName MyRenamedConfiguration

1
¿Qué es "MyRenamedConfiguration"?
Robert Noack

1
"MyRenamedConfiguration" es solo texto de marcador de posición como ejemplo. Podría haber cambiado el nombre de su Configuration.cs original a cualquier cosa (por ejemplo, FooBar, luego ejecute Update-Database -ConfigurationTypeName FooBar).
ckal

3
forma abreviada: Update-Database -conf MyRenamedConfiguration
Peter Kerr

100

Además de lo que sugirió @ckal, es fundamental darle a cada Configuration.cs renombrado su propio espacio de nombres. Si no lo hace, EF intentará aplicar las migraciones al contexto incorrecto.

Estos son los pasos específicos que funcionan bien para mí.

Si las migraciones están en mal estado y desea crear una nueva "línea de base":

  1. Elimine cualquier archivo .cs existente en la carpeta Migraciones
  2. En SSMS, elimine la tabla del sistema __MigrationHistory.

Creando la migración inicial:

  1. En la consola del Administrador de paquetes:

    Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextA -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextA
  2. En el Explorador de soluciones: cambie el nombre de Migrations.Configuration.cs a Migrations.ConfigurationA.cs. Esto debería cambiar automáticamente el nombre del constructor si usa Visual Studio. Asegúrate de que así sea. Editar ConfigurationA.cs: cambie el espacio de nombres a NamespaceOfContext.Migrations.MigrationsA

  3. Enable-Migrations -EnableAutomaticMigrations -ContextTypeName
    NamespaceOfContext.ContextB -ProjectName ProjectContextIsInIfNotMainOne
    -StartupProjectName NameOfMainProject  -ConnectionStringName ContextB
  4. En el Explorador de soluciones: cambie el nombre de Migrations.Configuration.cs a Migrations.ConfigurationB.cs. Nuevamente, asegúrese de que el nombre del constructor también sea apropiado. Editar ConfigurationB.cs: cambie el espacio de nombres a 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

Pasos para crear scripts de migración en Package Manager Console:

  1. Ejecutar comando

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

    o -

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

    Está bien volver a ejecutar este comando hasta que se apliquen los cambios a la base de datos.

  2. Ejecute los scripts en la base de datos local deseada o ejecute Update-Database sin -Script para aplicar localmente:

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

    o -

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

# 4 cambio: Editar ConfigurationA.cs -> Editar ConfigurationB.cs
Brian Rizo

1
@Biran: Gracias por darte cuenta. Edité la respuesta. Tenga en cuenta que también puede editar las respuestas usted mismo. Como aún no tiene una reputación de 2000, sus respuestas se envían a una cola de revisión, pero esa cola generalmente se procesa rápidamente, por lo que es probable que su edición se haya aprobado en unos minutos.
Eric J.

5
¡GRACIAS! Eso era lo que me faltaba (los espacios de nombres).
William M. Rawls

Esto puede ayudar porque no estaba claro para mí cómo hacer el cambio de nombre en los pasos 2 y 4 inicialmente: cuando cambia el nombre del archivo Configuration.cs a ConfigurationA.cs o ConfigurationB.cs, el cambio de nombre también debería dar como resultado la clase y su constructor también se renombra a ConfigurationA o ConfigurationB. Si no cambia el nombre de la clase, aparecerá un mensaje de error cuando ejecute el comando add-migration - "El tipo de configuración de migraciones 'ConfigurationA' no se encontró en el ensamblado '...'" - y sí, la redacción era mala al igual que eso en los mensajes de error que recibí en VS2013 - LOL
Greg Barth

3
esto me ayudó! instrucciones completas con todas las opciones y orden. me salvó horas
elcool

82

Me encontré con el mismo problema y utilicé la siguiente solución (todo desde la Consola del Administrador de paquetes)

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

Esto creará 2 carpetas separadas en la carpeta Migraciones. Cada uno contendrá el Configuration.csarchivo generado . Desafortunadamente, aún debe cambiar el nombre de esos Configuration.csarchivos, de lo contrario, habrá quejas por tener dos de ellos. Cambié el nombre de mis archivos a ConfigA.csyConfigB.cs

EDITAR : (cortesía de Kevin McPheat) Recuerde al cambiar el nombre de los archivos Configuration.cs, también cambie el nombre de los nombres de clase y los constructores / EDITAR

Con esta estructura puedes simplemente hacer

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

Que creará los archivos de código para la migración dentro de la carpeta junto a los archivos de configuración (esto es bueno para mantener esos archivos juntos)

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

Y por último, pero no menos importante, esos dos comandos aplicarán las migraciones correctas a sus bases de datos correspondientes.

EDITAR 08 de febrero de 2016: He hecho algunas pruebas con EF7 versión 7.0.0-rc1-16348

No pude hacer funcionar la opción -o | --outputDir. Siguió dandoMicrosoft.Dnx.Runtime.Common.Commandline.CommandParsingException: Unrecognized command or argument

Sin embargo, parece que la primera vez que se agrega una migración, se agrega a la carpeta Migraciones, y una migración posterior para otro contexto se coloca automáticamente en una subcarpeta de migraciones.

Los nombres originales ContextAparecen violar algunas convenciones de nomenclatura, por lo que ahora uso ContextAContexty ContextBContext. Usando estos nombres, podría usar los siguientes comandos: (tenga en cuenta que mi dnx todavía funciona desde la consola del administrador de paquetes y no me gusta abrir una ventana CMD separada para realizar migraciones)

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

Esto creará una instantánea del modelo y una migración inicial en la Migrationscarpeta para ContextAContext. Creará una carpeta con el nombre que ContextBcontiene estos archivos paraContextBContext

Agregué manualmente una ContextAcarpeta y moví los archivos de migración ContextAContexta esa carpeta. Luego cambié el nombre del espacio de nombres dentro de esos archivos (archivo de instantánea, migración inicial y tenga en cuenta que hay un tercer archivo debajo del archivo de migración inicial ... designer.cs). Tuve que agregar.ContextA al espacio de nombres, y desde allí el marco lo maneja automáticamente nuevamente.

El uso de los siguientes comandos crearía una nueva migración para cada contexto

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

y los archivos generados se colocan en las carpetas correctas.


5
la mejor solución, simple y mantenemos una carpeta clara.
Malick

2
Esta fue la respuesta que necesitaba. ¡El espacio de nombres agregado a través de -MigrationsDirectory fue la respuesta! Gracias.
Crob

1
Solución agradable y limpia. Gracias.
Stefan Cebulak

4
1,5 años después, estoy feliz de poder usar mi propia publicación para configurar un nuevo proyecto.
bart s

1
Tenga en cuenta que cuando lo ejecute add-migrationse le pedirá Name. Esto me desconcertó un poco ya que ya estaba proporcionando ConfigurationTypeNamey me molestó un poco cuando solo dijo Name:. Pero, por supuesto, el Nombre que quiere es la descripción 'legible por humanos' del cambio, por ejemplo. AddedProductso IncreaseLengthOfNameFields. En la carpeta Migraciones, obtendrá esto como parte del nombre de la clase, por lo que es fácil ver qué es qué. Entonces, en efecto, Namees como un comentario de registro.
Simon_Weaver

7

En caso de que ya tenga una "Configuración" con muchas migraciones y quiera mantenerla como está, siempre puede crear una nueva clase de "Configuración", asígnele otro nombre, como

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

entonces solo emita el comando

Add-Migration -ConfigurationTypeName MyNewContextConfiguration InitialMigrationName

y EF apoyará la migración sin problemas. Finalmente actualice su base de datos, a partir de ahora EF se quejará si no le dice qué configuración desea actualizar:

Update-Database -ConfigurationTypeName MyNewContextConfiguration 

Hecho.

No es necesario que se ocupe de Enable-Migrations, ya que se quejará de que la "Configuración" ya existe, y el cambio de nombre de su clase de configuración existente traerá problemas al historial de migración.

Puede apuntar a diferentes bases de datos, o la misma, todas las configuraciones compartirán la tabla __MigrationHistory muy bien.


4

Si existen más bases de datos, use los siguientes códigos en PowerShell

Add-Migration Starter -context EnrollmentAppContext 
  • 'Starter' es el nombre de la migración

  • 'EnrollmentAppContext' es el nombre del contexto de mi aplicación

Puede abrir PowerShell en VS haciendo: Tools->NuGet Package Manager->Package Manager Console


1
Eso me ayudó. ¡Gracias! :)
noobprogrammer

3

Para actualizar el tipo de base de datos siguientes códigos en PowerShell ...

Update-Database -context EnrollmentAppContext

* si existe más de una base de datos solo use estos códigos, de lo contrario no es necesario ..


0

EF 4.7 en realidad da una pista cuando ejecuta Enable-migrations en múltiples contextos.

Se encontró más de un tipo de contexto en el ensamblado '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.
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.