【问题标题】:Entity Framework CodeFirst Migrations, Running migrations with optional upgrading to newest changes实体框架代码优先迁移,运行迁移,可选择升级到最新更改
【发布时间】:2013-01-23 17:06:38
【问题描述】:

我们正在运行 Entity Framework 5,并带有 Code FirstMigrations Enabled。使用数据库初始化程序运行:MigrateToLatestVersion

我们有几个运行在最新稳定分支上的客户。当我们在主干/主控中开发新代码时,我们有时需要连接到在分支代码 fx 上运行的客户数据库。调试某种数据错误。

如果有人忘记切换到客户正在运行的分支,这可能是“危险的”,因为迁移会升级客户数据库以适应该人正在运行的任何代码。

一种解决方案是运行另一个不会迁移到最新版本的初始化程序。但是,当我们为新客户部署新系统或有人新加入团队并且需要启动并运行时,这将意味着更多的工作。

我们正在考虑通过在 app.config 中设置一个 bool 来设置代码是否应该“迁移到最新版本”,然后始终将其设置为 false 以进行开发,然后在部署给客户时对其进行转换来解决此问题。

通过这种方式,我们可以获得仍然让数据库自动更新到最新版本的好处,但不会有开发人员意外连接到旧版本代码系统以及迁移破坏该数据库的危险。

既然我们有了这个,我们基本上需要检查这个:

(简化代码)

if(Config.MigrateToLatestVersion || !databaseExists) 
{
  var initializer = new MigrateToLatestVersion<MyContext,MigrationConfiguration>();
  Database.SetInitializer(initializer);
  using(var context = new MyContext())
  {
    context.Database.Initialize(true)
  }
}

我的问题是关于如何在不运行迁移的情况下检查数据库是否存在,但我发现你可以这样做:

Database.SetInitializer<MyContext>(null);
var context = new MyContext();
var databaseExists = context.Database.Exists();

但如果我只在数据库不存在时或当我从包管理器控制台手动运行 Update-Database 时运行 MigrateToLatestVersion 初始化程序。

我有 2 个问题,首先:如果我的模型与数据库不同,我不再收到异常,我仍然希望这样做。 第二:它不运行位于我的 MigrationConfiguration 中的种子方法,我可能仍想运行它。

关于我如何仍然可以运行 Migrations Initializer 以获得所有好处的任何建议,但仍然有一些东西可以防止有人意外破坏我们的生产环境?

【问题讨论】:

    标签: ef-code-first configuration-files entity-framework-5 entity-framework-migrations config-transformation


    【解决方案1】:

    所以我采用的解决方案是创建一个名为 MigrateDatabaseToLatestIfLocal 的新 DatabaseInitializer

    看看MigrateDatabaseToLatestVersion 初始化程序是如何工作的,我做了一些非常相似的事情,不同之处在于检查数据库是否存在以及我们是在本地还是远程运行(借助配置转换来确定这一点。远程系统有它是在配置文件中转换的数据源。)

    public class MigrateDatabaseToLatestIfLocal<TContext, TMigrationsConfiguration> : IDatabaseInitializer<TContext>
            where TContext : DbContext
            where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
        {
            private DbMigrationsConfiguration _config;
    
            public MigrateDatabaseToLatestIfLocal()
            {
                this._config = (DbMigrationsConfiguration)Activator.CreateInstance<TMigrationsConfiguration>();
            }
    
            public MigrateDatabaseToLatestIfLocal(string connectionStringName)
            {
              MigrateDatabaseToLatestIfLocal<TContext, TMigrationsConfiguration> databaseToLatestVersion = this;
              var instance = Activator.CreateInstance<TMigrationsConfiguration>();
              instance.TargetDatabase = new DbConnectionInfo(connectionStringName);
                databaseToLatestVersion._config = instance;
            }
    
            public void InitializeDatabase(TContext context)
            {
                var databaseExists = context.Database.Exists();
    
                var migrator = new DbMigrator(this._config);
                var pendingMigrations = migrator.GetPendingMigrations().OrderByDescending(s => s);
                var localMigrations = migrator.GetLocalMigrations().OrderByDescending(s => s);
                var dbMigrations = migrator.GetDatabaseMigrations().OrderByDescending(s => s);
    
    
                var isRemoteConnection = FunctionToFindOutIfWeAreRemote(); //here we check the config file to see if the datasource is a certain IP, this differentiates locally and remotely because of config tranformation.
    
                if (isRemoteConnection && databaseExists)
                {
                    if (pendingMigrations.Any())
                    {
                        throw new MigrationsException("You are not allowed to automatically update the database remotely.")
                    }
                    if (localMigrations.First() != dbMigrations.First())
                    {
                        throw new MigrationsException("Migrations in code and database dont match, please make sure you are running the code supported by the remote system. ");
                    }
                }
                else
                {
                    //we are local, fine update the db and run seeding.
                    //we are remote and the db does not exist, fine update and run seed.
                    migrator.Update();
                }
            }
        }
    

    这可能是一个非常特殊的情况,但对我来说,它在运行代码优先迁移时提供了一些安全性,确保您不会意外地随机迁移实时环境

    【讨论】:

      猜你喜欢
      • 2013-12-29
      • 1970-01-01
      • 1970-01-01
      • 2013-09-16
      • 1970-01-01
      • 2017-10-31
      相关资源
      最近更新 更多