3

我们正在运行带有Code FirstMigrations Enabled的Entity Framework 5。使用数据库初始化程序运行: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();

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

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

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

4

1 回答 1

4

所以我采用的解决方案是制作一个名为的新 DatabaseInitializerMigrateDatabaseToLatestIfLocal

看看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-01-30T12:42:50.073 回答