entity-framework - name - entity framework code first
ConfusiĆ³n sobre EF Auto Migrations y siembra-sembrando cada inicio de programa (3)
El hecho de que el método Seed se ejecutara solo cuando la base de datos cambiaba era bastante limitante para los inicializadores de base de datos enviados en EF 4.1. Era limitante porque a veces era necesario actualizar los datos iniciales sin cambiar la base de datos, pero para que eso ocurriera, tenía que hacer que, artificialmente, pareciera que la base de datos había cambiado.
Con Migrations, el uso de Seed se volvió un poco diferente porque ya no se podía suponer que la base de datos comenzaba vacía; ese es el punto de Migrations después de todo. Por lo tanto, un método de Seed en Migrations debe suponer que la base de datos existe y puede que ya tenga datos, pero es posible que sea necesario actualizar esos datos para tener en cuenta los cambios realizados en la base de datos para las Migraciones. De ahí el uso de AddOrUpdate.
Entonces ahora tenemos una situación en la que Seed debe escribirse para tener en cuenta los datos existentes, lo que significa que realmente no hay necesidad de perpetuar las limitaciones del método de semilla de EF 4.1 de forma que parezca que la base de datos ha cambiado. solo para hacer que Seed se ejecute. Por lo tanto, Seed ahora se ejecuta cada vez que el contexto se usa por primera vez en el dominio de la aplicación. Esto no debería cambiar la forma en que se incorpora Seed ya que necesita manejar el caso donde los datos ya están presentes de todos modos.
Si causa problemas de perfusión porque tiene muchos datos de Semilla, generalmente es muy fácil agregar comprobaciones en el método de Semilla que consulta la base de datos para determinar cuánto trabajo se debe hacer antes de hacerlo.
Recientemente cambié una aplicación de usar lo siguiente para dev:
DropCreateDatabaseIfModelChanges<Context>
Para usar:
public class MyDbMigrationsConfiguration: DbMigrationsConfiguration<GrsEntities>
{
public MyDbMigrationsConfiguration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
}
En mi contexto db tengo:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Tell Code First to ignore PluralizingTableName convention
// If you keep this convention then the generated tables will have pluralized names.
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//set the initializer to migration
Database.SetInitializer(new MigrateDatabaseToLatestVersion<GrsEntities, MigrationConfig>());
}
He reemplazado a Seed (contexto) en DbMigrationsConfiguration usando la extensión AddOrUpdate donde estaba usando Agregar antes con siembra en el drop db (DropCreateDatabaseIfModelChanges).
Mi confusión es que la migración se ejecuta con cada inicio de la aplicación, independientemente de que haya algún cambio en el DbContext. Cada vez que inicio la aplicación (la biblioteca se ejecuta a través de un servicio) el inicializador se ejecuta igual que la semilla. Mi comportamiento esperado es comprobar si una migración es necesaria (verificar entre bastidores para ver si el modelo coincide con la base de datos física) luego actualizar las tablas / columnas nuevas / eliminadas y solo ejecutar la semilla si algo ha cambiado.
En mi prueba, la semilla se ejecuta todo el tiempo, lo cual es viable pero aparentemente ineficiente y no era lo que esperaba. Lamentablemente, la documentación de MSDN es bastante limitada.
¿Estoy haciendo un uso indebido completo de MigrateDatabaseToLatestVersion? ¿Hay alguna manera de obtener el comportamiento que espero (es decir, solo semilla si hay un cambio de modelo) o debería simplemente cambiar mi método de inicialización para esperar que se ejecute cada lanzamiento de la aplicación?
Estoy un tanto de acuerdo con la respuesta de , sin embargo IMO Seed es para DbMigrations y no quiero que el método Seed compruebe todo todo el tiempo, por ejemplo, si tengo 4 migraciones, entonces tendría que probar de alguna manera qué datos se deben sembrar y serán 4 hits más de la base de datos al menos. En caso de que aún desee tener el comportamiento de ejecutar el método Seed solo cuando se aplican migraciones, como yo, vine con mi propia implementación de la estrategia IDatabaseInitializer
public class CheckAndMigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration>
: IDatabaseInitializer<TContext>
where TContext : DbContext
where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
{
public virtual void InitializeDatabase(TContext context)
{
var migratorBase = ((MigratorBase)new DbMigrator(Activator.CreateInstance<TMigrationsConfiguration>()));
if (migratorBase.GetPendingMigrations().Any())
migratorBase.Update();
}
}
Otra opción podría ser cargar una clase de inicializador db personalizada en tiempo de ejecución dentro del método de inicialización. La aplicación de producción podría cargar un inicializador ficticio, mientras que la aplicación de desarrollo podría cargar el inicializador real. Podría usar Unity / MEF
// Unity Dependency Injection Prop
[Dependency]
property IMyInitializer initializer;
protected override Seed(YourContextClass context)
{
initializer.Seed(context);
}
Algo como eso. Luego, debe cambiar los inicializadores una vez que tenga la configuración de la base de datos en Producción, en la unidad ficticia, eso no haría nada.