将InitialCreate迁移插入数据库而不执行架构更改

时间:2016-03-18 17:30:24

标签: entity-framework-6 ef-migrations

我正在将Code First迁移添加到现有数据库的现有Entity Framework 6域中。我需要以下行为:

  1. 如果数据库存在,请插入InitialCreate迁移,但不要执行迁移Up()的内容。
  2. 如果数据库不存在,请创建它并运行Up()Down()的内容以创建一个空的但正确的架构数据库。
  3. 当我通过Continuous Delivery部署发布时,我需要(1)。我需要(2)当开发人员正在清理他们的机器并开始新鲜时。我不想使用自动迁移。

    我很欣赏Migration没有数据库上下文的概念,它只负责生成一系列SQL指令。

    这些是我唯一的选择吗?

    1。将Up和Down的内容移出InitialCreate并进入Configuration.Seed

    InitialCreate迁移运行Up()但未进行任何更改。在Seed()中,我们可以访问DbContext,因此我们可以确定表是否存在,并在需要时创建它们。

    我认为,在迁移后调用Seed()时需要运行大量迁移时,这可能会中断。在空数据库上,在更新这些模式之后将发生表的创建。

    2。将Up()方法作为SQL脚本执行

    迁移允许开发人员将内联SQL放入Up()Down()。将数据库的创建移动到内联SQL,并在顶部添加IF NOT EXISTS

    我不喜欢这样,因为您无法使用随InitialCreate提供的模型。如果模型已更新,则固定的SQL字符串不会出现。

    第3。清空Up()和Down()方法,执行发布,重新创建代码,执行另一个发布

    第一次运行InitialCreate迁移时,它不会有任何内容。该条目将进入迁移数据库而不运行任何内容。

    一旦执行了第一个版本,我就可以重新创建创建代码,这样当未来的开发人员在没有数据库的情况下运行它时,它将正确创建。

    注意:这是我最喜欢的,因为它使用了Entity Framework,我可以亲自控制在发布后添加代码。

    有更好的方法吗?

    修改

    我无法从空构建数据库,这可能与Context模型创建有关。它使用一种定制的可插拔方法:

        public MyObjectContext()
        {
            ((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;
            ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = 180;
        }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            System.Type configType = typeof(AnswerMap);   //any of your configuration classes here
            var typesToRegister = Assembly.GetAssembly(configType).GetTypes()
            .Where(type => !String.IsNullOrEmpty(type.Namespace))
            .Where(type => type.BaseType != null && type.BaseType.IsGenericType && type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
            foreach (var type in typesToRegister)
            {
                dynamic configurationInstance = Activator.CreateInstance(type);
                modelBuilder.Configurations.Add(configurationInstance);
            }
            base.OnModelCreating(modelBuilder);
        }
    

    所有地图对象都在同一个DLL中,用于数据库表的域实体位于单独的DLL中。

1 个答案:

答案 0 :(得分:2)

这就是我们的工作:

1)创建一个初始迁移,它是当前数据库的快照。使用-IgnoreChanges可以将任何代码保留在Up()之外。您不需要Up()代码,因为EF会将先前的模型(空白)与迁移中存储的模型进行比较,并意识到您需要在快照时添加所有现有对象。

add-migration Initial -IgnoreChanges

2)在开发时添加新的迁移。在团队环境中,您可能会遇到此处列出的问题:https://msdn.microsoft.com/en-US/data/dn481501

3)您可以生成一个幂等脚本,该脚本将从头开始重建整个系统并应用任何(或所有)迁移。

Update-Database -Script -SourceMigration $InitialDatabase

https://msdn.microsoft.com/en-us/data/jj591621.aspx?f=255&MSPPError=-2147217396#idempotent