asp.net mvc - studio - Migraciones de Entity Framework 5: configuración de una migración inicial y una semilla única de la base de datos
entity framework core migrations (4)
Tengo una aplicación MVC4 que recientemente actualicé a Entity Framework 5 y estoy tratando de mover nuestra base de datos a usar migraciones desde el estilo de desarrollo de colocar y crear cada ejecución.
Esto es lo que hice en la función de inicio de mi aplicación.
protected void Application_Start()
{
Database.SetInitializer(
new MigrateDatabaseToLatestVersion< MyContext, Configuration >() );
...
}
Ejecuté el comando Enable-Migrations
en mi proyecto de repositorios y pensé que esto crearía un archivo de migración inicial; sin embargo, el único archivo que creó fue Configuration
Cuando elimino la base de datos, la crea como se esperaba a través del código primero y se siembra la base de datos desde el archivo de Configuración. En el archivo de configuración, cambié todas las funciones Add()
a AddOrUpdate()
Sin embargo, ejecuta la función de inicialización en mi archivo de Configuration
cada vez que se inicia el sitio web y duplica todos los datos de inicialización una y otra vez.
Imaginé que crearía un archivo de initial migration
ya que el blog que leí sugirió que sí y podría poner los datos de initial migration
allí, pero no fue así.
¿Alguien puede explicar cómo debo configurar DB en el código para que solo se reproduzca una vez?
LINK: la publicación del blog de migraciones que seguí
Si bien esto es bastante interesante para usar EF migrate.exe, desde entonces he cambiado al uso de roundhouse para ejecutar migraciones. Todavía utilizo EF para anclar mis migraciones según los modelos, pero escribí una pequeña aplicación de consola para escribir las migraciones en los archivos SQL. Luego uso Roundhouse para realizar las migraciones a través de mis scripts de creación de rake. Hay un poco más de proceso involucrado, pero es mucho más estable que usar EF para realizar las migraciones sobre la marcha cuando se inicia la aplicación.
¿Podría agregar una migración manualmente y llenarla con el código de siembra que desee? En la consola del administrador de paquetes, ejecute:
Add-Migration [Name]
Luego puede editar ese archivo creado para usted en su carpeta de migraciones.
En mi proyecto, en realidad sí estoy sembrando como Richard en el método Seed de la configuración de contexto. Realmente no tengo preferencia Pero las migraciones deberían ser más eficientes, ya que la aplicación no necesita verificar si las filas existen en la base de datos cuando se inicia la aplicación. Solo es necesario verificar si la migración se ha ejecutado, lo que debería ser más rápido.
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
// If you want automatic migrations as well uncomment below.
// You can use both manual and automatic at the same time, but I don''t recommend it.
//AutomaticMigrationsEnabled = true;
//AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(MyContext context)
{
// This method will be called after migrating to the latest version.
// You can use the DbSet<T>.AddOrUpdate() helper extension method
// to avoid creating duplicate seed data.
context.FontFamilies.AddOrUpdate(
f => f.Id,
new FontFamily { Id = 1, PcName = "Arial" },
new FontFamily { Id = 2, PcName = "Times New Roman" },
});
Estoy usando esto en Global.asax:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// Any migrations that haven''t been applied before will
// automatically be applied on Application Pool restart
Database.SetInitializer<MyContext>(
new MigrateDatabaseToLatestVersion<MyContext,
MyApp.Migrations.Configuration>()
);
}
}
Esta ha demostrado ser una publicación popular, así que la actualicé a la luz de los comentarios de los demás. Lo principal que debe saber es que el método Seed en la clase Configuration se ejecuta CADA vez que se inicia la aplicación, que no es lo que implica el comentario en el método de la plantilla. Vea la respuesta de alguien en Microsoft a esta post sobre por qué es eso, gracias a Jason Learmouth por encontrarlo.
Si usted, como yo, solo desea ejecutar las actualizaciones de la base de datos si hay migraciones pendientes, entonces necesita hacer un poco más de trabajo. Puede averiguarlo si hay migraciones pendientes al llamar a migrator.GetPendingMigrations (), pero debe hacerlo en el directorio a medida que se borra la lista de migraciones pendientes antes de llamar al método Seed. El código para implementar esto, que va en la clase Migrations.Configuration es el siguiente:
internal sealed class Configuration : DbMigrationsConfiguration<YourDbContext>
{
private readonly bool _pendingMigrations;
public Configuration()
{
// If you want automatic migrations the uncomment the line below.
//AutomaticMigrationsEnabled = true;
var migrator = new DbMigrator(this);
_pendingMigrations = migrator.GetPendingMigrations().Any();
}
protected override void Seed(MyDbContext context)
{
//Microsoft comment says "This method will be called after migrating to the latest version."
//However my testing shows that it is called every time the software starts
//Exit if there aren''t any pending migrations
if (!_pendingMigrations) return;
//else run your code to seed the database, e.g.
context.Foos.AddOrUpdate( new Foo { bar = true});
}
}
Debo señalar que algunas personas han sugerido poner el código semilla en el código de migración real ''arriba''. Esto funciona, pero significa que debe recordar poner el código de semilla en cada nueva migración y es bastante difícil recordarlo, así que no haría eso. Sin embargo, si su semilla cambia con cada migración, esa podría ser una buena manera de hacerlo.
Esto es algo que también me he preguntado en el pasado. Tengo ciertas tablas en mi base de datos que se completan en mi evento Seed, y ahora solo compruebo si una de ellas está vacía dentro del método Seed. Si hay filas, el método Seed no se ejecuta. No es infalible, pero sí el truco.
La respuesta a post explica por qué Seed se ejecuta cada vez que se ejecuta la aplicación.
Yo uso el método de Jon Smiths, pero he puesto el cheque para la declaración de migraciones pendientes en un bloque #if como este:
#if (!DEBUG)
if (!_pendingMigrations) return;
#endif
De esa forma, cuando estoy depurando, el método Seed siempre se ejecuta para volver a llenar mis datos de inicialización, lo cual es útil cuando lo elimino durante las pruebas, etc. pero no obtengo el resultado de perf cuando está en lanzamiento.