La mejor forma de generar datos de forma incremental en Entity Framework 4.3
entity-framework ef-migrations (2)
He estado utilizando Entity Framework 4.3 en una base de datos existente y tengo un par de escenarios que estoy intentando atender.
En primer lugar, si elimino mi base de datos, me gustaría que EF la recreara desde cero: he utilizado con éxito un inicializador de base de datos CreateDatabaseIfNotExists para esto.
En segundo lugar, si actualizo mi modelo y la base de datos ya existe, me gustaría que la base de datos se actualice automáticamente; he utilizado satisfactoriamente Migraciones de Entity Framework 4.3 para esto.
Así que aquí está mi pregunta. Digamos que agrego una nueva tabla a mi modelo que requiere algunos datos de referencia, ¿cuál es la mejor manera de garantizar que estos datos se creen tanto cuando se ejecuta el inicio de la base de datos como cuando se ejecuta la migración? Mi deseo es que los datos se creen cuando estoy creando el archivo desde cero y también cuando la base de datos se actualice como resultado de una migración en ejecución.
En algunos ejemplos de migraciones EF, he visto personas usar la función SQL () en el método UP de la migración para crear datos iniciales, pero si es posible preferiría usar el contexto para crear los datos iniciales (como puede ver en la mayoría de los ejemplos de inicializadores de bases de datos) ya que me parece extraño que usas sql puro cuando la idea completa de EF está abstrayendo eso. Intenté utilizar el contexto en el método UP pero, por alguna razón, no creía que existiera una tabla creada en la migración cuando intenté agregar los datos iniciales directamente debajo de la llamada para crear la tabla.
Cualquier sabiduría muy apreciada.
No recomendaría el uso de llamadas Sql()
en su método Up()
porque (IMO) esto está realmente destinado al código de migración real para el cual no hay función incorporada, en lugar de código semilla.
Me gusta pensar en datos semilla como algo que podría cambiar en el futuro (incluso si mi esquema no), así que simplemente escribo controles "defensivos" alrededor de todos mis insertos en la función semilla para asegurarme de que la operación no se disparó previamente.
Considere un escenario donde tiene una tabla de "Tipos" que comienza con 3 entradas, pero luego agrega un 4to. No debería necesitar una "migración" para solucionar esto.
El uso de Seed()
también le brinda un contexto completo para trabajar, lo cual es mucho mejor que usar las cadenas simples sql en el método Sql()
que demostró Ladislav.
Además, tenga en cuenta que la ventaja de usar métodos integrados de EF tanto para el código de migración como para el código de inicialización es que las operaciones de su base de datos permanecen neutrales a la plataforma. Esto significa que los cambios en el esquema y las consultas se pueden ejecutar en Oracle, Postgre, etc. Si escribe SQL en bruto real, entonces potencialmente se podrá encerrar innecesariamente.
Es posible que esté menos preocupado por esto, ya que el 90% de las personas que usan EF solo llegarán a SQL Server, pero lo estoy lanzando para ofrecerle una perspectiva diferente de la solución.
Si desea usar entidades para inicializar datos, debe usar el método Seed
en su configuración de migraciones. Si genera nuevo proyecto Enable-Migrations
, obtendrá esta clase de configuración:
internal sealed class Configuration : DbMigrationsConfiguration<YourContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(CFMigrationsWithNoMagic.BlogContext 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. E.g.
//
// context.People.AddOrUpdate(
// p => p.FullName,
// new Person { FullName = "Andrew Peters" },
// new Person { FullName = "Brice Lambson" },
// new Person { FullName = "Rowan Miller" }
// );
//
}
}
La forma en que las migraciones generan datos no es muy eficiente porque se supone que debe usarse para una siembra muy básica. Cada actualización de la nueva versión pasará por un conjunto completo e intentará actualizar los datos existentes o insertar nuevos datos. Si no utiliza el método de extensión AddOrUpdate
, debe asegurarse manualmente de que los datos se incorporen a la base de datos solo si aún no están presentes.
Si desea una manera eficiente de sembrar porque debe sembrar muchos datos, obtendrá mejores resultados con los mismos:
public partial class SomeMigration : DbMigration
{
public override void Up()
{
...
Sql("UPDATE ...");
Sql("INSERT ...");
}
public override void Down()
{
...
}
}