首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对EF自动迁移和播种的困惑-在计划开始时播种

对EF自动迁移和播种的困惑-在计划开始时播种
EN

Stack Overflow用户
提问于 2012-05-31 03:05:11
回答 3查看 19.1K关注 0票数 42

我最近更改了一个应用程序,不再使用下面的dev:

代码语言:javascript
复制
DropCreateDatabaseIfModelChanges<Context>

使用:

代码语言:javascript
复制
public class MyDbMigrationsConfiguration: DbMigrationsConfiguration<GrsEntities>
{
    public MyDbMigrationsConfiguration()
    {
        AutomaticMigrationsEnabled = true;
        AutomaticMigrationDataLossAllowed = true;
    }
}

在我的db上下文中,我有:

代码语言:javascript
复制
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>());
}

我已经使用AddOrUpdate扩展覆盖了DbMigrationsConfiguration中的种子(上下文),而我只是在drop数据库(DropCreateDatabaseIfModelChanges)上使用了添加之前的种子。

我的困惑是,无论DbContext是否有任何更改,迁移都会随着应用程序的每次启动而运行。每次启动应用程序(库通过服务运行)时,初始化器都会像种子一样运行。我的预期行为是检查迁移是否必要(在幕后检查模型是否与物理数据库匹配),然后更新任何新的/删除的表/列,并仅在某些情况发生变化时运行种子。

在我的测试中,种子每次都在运行,这是可行的,但似乎效率很低,而且不是我所期望的。不幸的是,MSDN文档非常有限。

我是不是完全滥用了MigrateDatabaseToLatestVersion?有没有办法获得我期望的行为(也就是,如果模型发生了变化,就只能使用seed ),或者我是否应该更改seed方法,使其在每次应用程序启动时都能运行?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-05-31 08:39:07

Seed方法仅在数据库更改时运行,这一事实对于EF 4.1中附带的数据库初始化器来说是相当有限的。这是有限制的,因为有时您需要在不更改数据库的情况下更新种子数据,但要做到这一点,您必须人为地使其看起来数据库已经更改。

对于迁移,Seed的使用有点不同,因为不能再假设数据库是空的--毕竟这就是迁移的要点。因此,迁移中的种子方法必须假设数据库存在,并且其中可能已经有数据,但是可能需要更新数据,以考虑到迁移对数据库所做的更改。因此使用了AddOrUpdate。

所以现在我们有了这样一种情况,Seed必须考虑到现有的数据,这意味着实际上没有必要延续EF 4.1 Seed方法的限制,这样您就必须让数据库看起来像是发生了变化,才能让Seed运行。因此,Seed现在每次在应用程序域中第一次使用上下文时都会运行。这不应该改变Seed的实现方式,因为它需要处理数据已经存在的情况。

如果因为您有大量的种子数据而导致性能问题,那么通常很容易将检查添加到种子方法中,以查询数据库以确定在执行此操作之前需要完成多少工作。

票数 61
EN

Stack Overflow用户

发布于 2015-01-17 03:23:51

我在某种程度上同意Arthur Vickers的回答,然而IMO Seed是用于DbMigrations的,我不希望Seed方法每次都检查所有东西,例如,如果我有4个迁移,那么我将需要以某种方式测试哪些数据必须是种子数据,这将是至少4个以上的数据库命中。如果您仍然希望只有在应用迁移时才运行种子方法的行为,就像我一样,我提供了自己的IDatabaseInitializer策略实现

代码语言:javascript
复制
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();
    }
}
票数 18
EN

Stack Overflow用户

发布于 2012-10-14 20:41:04

另一种选择可以是在运行时在种子方法中加载自定义db初始化器类。然后,生产应用程序可以加载虚拟初始化器,而开发应用程序可以加载真正的初始化器。你可以使用Unity/MEF

代码语言:javascript
复制
    // Unity Dependency Injection Prop
    [Dependency]
    property IMyInitializer initializer;

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

差不多吧。一旦在生产环境中设置了DB,您就可以将初始化器切换到虚拟数据库,这将不会做任何事情。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10822618

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档