La mejor manera de sembrar datos de forma incremental en Entity Framework 4.3


He estado usando Entity Framework 4.3 en una base de datos existente y tengo un par de escenarios que estoy tratando de atender.

En primer lugar, si elimino mi base de datos me gustaría que EF recreara si 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 actualizara automáticamente - he utilizado Entity Framework 4.3 con éxito Migraciones 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 inicializador de base de datos como cuando se ejecuta la migración. Mi deseo es que los datos se crean cuando estoy creando la base de datos desde cero y también cuando la base de datos se actualiza como resultado de una migración en ejecución.

En algunos ejemplos de migraciones EF he visto a personas usar la función SQL() en el método UP de la migración para crear datos de semilla, pero si es posible, preferiría usar el contexto para crear los datos de semilla (como se ve en la mayoría de los ejemplos de inicializador de bases de datos), ya que me parece extraño que use sql puro cuando toda la idea de EF es abstraerlo. He intentado usar el contexto en el método UP, pero por alguna razón no pensé que existiera una tabla que se creó en la migración cuando intenté agregar los datos de semilla directamente debajo de la llamada para crear el tabla.

Cualquier sabiduría es muy apreciada.

Author: Ladislav Mrnka, 2012-02-18

2 answers

Si desea usar entidades para sembrar datos, debe usar el método Seed en su configuración de migraciones. Si generas fresh project Enable-Migrations obtendrás 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 los datos de semilla de migraciones no son muy eficientes porque se supone que deben usarse para una siembra muy básica. Cada actualización a una nueva versión pasará por todo el conjunto 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 envían a la base de datos solo si no están presentes todavía.

Si desea una forma eficiente de siembra porque debe sembrar o muchos datos obtendrá un mejor resultado con common:

public partial class SomeMigration : DbMigration
{
    public override void Up()
    {
        ...
        Sql("UPDATE ...");
        Sql("INSERT ...");
    }

    public override void Down()
    {
        ...
    }
}
 54
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-02-18 19:08:46

No recomendaría usar llamadas Sql() en su método Up() porque (IMO) esto está realmente destinado a código de migración real para el que no hay una función incorporada, en lugar de código semilla.

Me gusta pensar en los datos de semilla como algo que podría cambiar en el futuro (incluso si mi esquema no lo hace), así que simplemente escribo comprobaciones "defensivas" alrededor de todas mis inserciones en la función de semilla para asegurarme de que la operación no se activó anteriormente.

Considere un escenario donde usted tiene un Tabla" Tipos " que comienza con 3 entradas, pero luego agrega una 4ta. No debería necesitar una "migración" para abordar esto.

Usar Seed() también le da un contexto completo para trabajar, que es mucho mejor que usar las cadenas sql simples en el método Sql() que Ladislav demostró.

Además, tenga en cuenta que el beneficio de usar métodos EF integrados tanto para el código de migración como para el código semilla es que las operaciones de su base de datos permanecen neutrales para la plataforma. Esto significa que su esquema los cambios y consultas pueden ejecutarse en Oracle, Postgre, etc. Si escribe SQL raw real, entonces potencialmente se está bloqueando 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 solo lo estoy lanzando para darle una perspectiva diferente sobre la solución.

 32
Author: Roger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-11 08:09:10