实体框架代码首先使用现有数据库迁移策略

时间:2014-09-21 09:35:00

标签: c# sql-server database entity-framework

我遇到以下情况,无法确定正确的迁移策略。帮助很感激。

  • 应用程序创建并使用数据库作为数据存储
  • 应用程序需要在启动时更新数据库如果需要
  • 使用 Nuget Manager控制台不是一个选项。 (出于迁移目的,本地没问题)
  • 我在分发中存在非EF的数据库

现在我想开始使用EF代码第一种方法。我需要实现的是:

  1. 如果没有数据库则创建一个
  2. 如果数据库存在,则使用空迁移(只是为下次升级做好准备)
  3. 这应该在应用程序启动时发生
  4. 数据库不存在====>创建EF初始=====> Upg v1 =====> Upg V2

    数据库存在=====>跳过初始但准备好进行下一次升级=====> Upg v1 ======> Upg v2

    感谢您的帮助

    其他信息: 这是存在的数据库(只是一个例子):

    CREATE DATABASE Test
    GO
    
    Use Test
    GO
    CREATE SCHEMA [TestSchema] AUTHORIZATION [dbo]
    GO
    CREATE TABLE [TestSchema].[Table1](
        [Id] [uniqueidentifier] NOT NULL,
        [Column1] [nvarchar](500) NOT NULL,
        [Column2] [bit] NOT NULL,
        [Column3] [bit] NOT NULL,
     CONSTRAINT [PK_MonitorGroups] PRIMARY KEY CLUSTERED 
    (
        [Id] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    

    使用逆向工程EF创建了初始迁移:

    public partial class Initial : DbMigration
        {
            public override void Up()
            {
                CreateTable(
                    "TestSchema.Table1",
                    c => new
                        {
                            Id = c.Guid(nullable: false),
                            Column1 = c.String(nullable: false, maxLength: 500),
                            Column2 = c.Boolean(nullable: false),
                            Column3 = c.Boolean(nullable: false),
                        })
                    .PrimaryKey(t => t.Id);
            }
    
            public override void Down()
            {
                DropTable("TestSchema.Table1");
            }
        }
    

    如果我使用@spender提供的代码对不存在的数据库,一切都很酷。 如果我在现有数据库中使用它,它将一直有效,直到我更改模型(下一次迁移)。

    我所看到的是,迁移返回的升级脚本包含整个数据库创建。并且不能对已有的对象执行。

    实际上可以工作的是将迁移表添加到现有数据库并添加初始数据,但我不确定这是一个很好的解决方案。

1 个答案:

答案 0 :(得分:17)

我花了很长时间才弄明白,所以我很乐意在这里分享。

首先,您需要对数据库进行逆向工程。 Entity framework power tools可以为您完成此操作。安装完成后,在项目中,使用nuget安装EF,右键单击解决方案资源管理器中的项目节点,然后Entity Framework - > Reverse Engineer Code First。这将为您的项目生成一大堆模型类和映射类。

接下来,在软件包管理器控制台中

Enable-Migrations

然后

Add-Migration Initial

创建描述从空DB到当前架构的转换的迁移。

现在编辑生成的Configuration.cs类构造函数:

    public Configuration()
    {

        AutomaticMigrationsEnabled = false;
        AutomaticMigrationDataLossAllowed = false;
    }

接下来,在应用启动时,(如果您从网络服务器运行,可能在global.asax Application_Start中),您需要触发迁移。这种方法可以完成这项工作:

    public static void ApplyDatabaseMigrations()
    {
        //Configuration is the class created by Enable-Migrations
        DbMigrationsConfiguration dbMgConfig = new Configuration()
        {
            //DbContext subclass generated by EF power tools
            ContextType = typeof(MyDbContext)
        };
        using (var databaseContext = new MyDbContext())
        {
            try
            {
                var database = databaseContext.Database;
                var migrationConfiguration = dbMgConfig;
                migrationConfiguration.TargetDatabase =
                    new DbConnectionInfo(database.Connection.ConnectionString,
                                         "System.Data.SqlClient");
                var migrator = new DbMigrator(migrationConfiguration);
                migrator.Update();
            }
            catch (AutomaticDataLossException adle)
            {
                dbMgConfig.AutomaticMigrationDataLossAllowed = true;
                var mg = new DbMigrator(dbMgConfig);
                var scriptor = new MigratorScriptingDecorator(mg);
                string script = scriptor.ScriptUpdate(null, null);
                throw new Exception(adle.Message + " : " + script);
            }
        }
    }

现在您可以正常添加更多迁移。当应用运行时,如果尚未应用这些迁移,则会在调用ApplyDatabaseMigrations时应用这些迁移。

现在你正好在EF代码优先折叠中。我认为那就是你问的,对吧?