混淆EF自动迁移和播种 - 播种每个程序启动(Confusion over EF Auto Migr

2019-06-25 00:04发布

我最近刚从用于开发以下变化的应用程序:

DropCreateDatabaseIfModelChanges<Context>


要使用:

public class MyDbMigrationsConfiguration: DbMigrationsConfiguration<GrsEntities>
{
    public MyDbMigrationsConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
}


在我的数据库方面,我有:

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>());
}

我一直在使用,我只是用用就降分贝(DropCreateDatabaseIfModelChanges)播种前添加AddOrUpdate扩展在DbMigrationsConfiguration覆盖种子(上下文)。

我的困惑是,迁移与应用程序的每一个开始,无论是有向的DbContext任何更改的运行。 每一次我(通过服务库运行)启动应用程序初始化运行一样的种子。 我预期的行为是检查迁移是否是必要的(幕后检查,看看模型物理数据库匹配),那么更新任何新/删除表/列且仅当事情已经改变运行的种子。

在我的测试运行的种子每一次,这是可行的,但似乎效率不高,并没有我所期望的。 不幸的是,MSDN文档是相当有限的。

我是不是完全滥​​用MigrateDatabaseToLatestVersion? 有没有什么办法让我想到(即仅当有一个模型改变种子),或者我应该改变我的种子法的期望要运行的每个应用程序启动的行为?

Answer 1:

当数据库发生变化是相当限制为发运在EF 4.1数据库的初始化种子法只跑了的事实。 这是限制,因为有时你需要在不改变数据库更新种子数据,但要做到这一点,你不得不人为地使它看起来像数据库发生了变化。

随着迁移使用种子变得有点不同,因为它再也不能假定该数据库已经开始为空 - 这是一种迁移后所有的点。 因此,在迁移种子方法假设数据库存在,可能已经在它的数据,但这些数据可能需要进行更新,以考虑到数据库的迁移所做的更改。 因此,使用AddOrUpdate的。

所以,现在我们已经在那里种必须写入考虑现有数据的情况下,这意味着,我们实在没有必要延续以往的EF 4.1种方法的限制,例如,你将不得不让它看起来数据库发生了变化只是为了得到种子运行。 因此,现在的种子每次运行的背景下,用于在应用程序域第一次时间。 这不应该改变籽方式imlemented因为它需要处理其中的数据已经存在反正情况。

如果它会导致PERF的问题,因为你有很多种子的数据,那么它通常是安静容易检查加入到该查询的数据库,以确定需要多少工作做前需做种子的方法。



Answer 2:

我有些同意阿瑟·维克斯响应,但IMO种子是DbMigrations,我不希望种方法可以在每次检查的一切,例如,如果我有4个迁移,那么我会需要以某种方式测试数据必须播种和将4个数据库的访问至少。 如果你仍然想有正在运行的种子法的行为,只有当迁移应用,像我一样,我带着我自己实施的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();
    }
}


Answer 3:

另一种选择可能是种子的方法中在运行时加载的自定义分贝初始化类。 那么生产应用可以加载一个虚拟的初始化,而开发的应用程序可以加载真正的初始化。 你可以使用统一/ MEF

    // Unity Dependency Injection Prop
    [Dependency]
    property IMyInitializer initializer;

    protected override Seed(YourContextClass context)
    {
       initializer.Seed(context);
    }

类似的东西。 然后你会切换初始化一旦你在生产数据库的建立,到虚拟一个,那什么都不做。



文章来源: Confusion over EF Auto Migrations and seeding - seeding every program start