public void CheckAndCreateMigrationTable(Instance instance, Execution currentExecution) { currentExecution.AppendLog("Checking migration tables on {0}...", instance.FullName); using (SqlConnection connection = new SqlConnection(connectionStringProvider.GetConnectionString(instance))) { connection.Open(); using (SqlCommand cmd = new SqlCommand(@"SELECT COUNT(*) FROM sys.objects WHERE name='DBAppliedMigrations' AND type_desc = 'USER_TABLE'", connection)) { int count = (int)cmd.ExecuteScalar(); if (count == 0) { currentExecution.AppendLog("No migrations tables detected. Installing...", instance.FullName); cmd.CommandText = @"CREATE TABLE [DBAppliedMigrations]( [Id] [int] IDENTITY(1,1) NOT NULL, [Executed_at] [datetime] NULL, [Executed_by] [nvarchar](255) NULL, [MigrateScript] [ntext] NULL, [RollbackScript] [ntext] NULL, [Migration_id] [int] NULL, PRIMARY KEY CLUSTERED ( [Id] ASC ) )"; cmd.ExecuteNonQuery(); currentExecution.AppendLog("Migrations tables installed.", instance.FullName); } else { currentExecution.AppendLog("Migration tables already installed on {0}.", instance.FullName); } } } }
public Execution AsyncBeginApply(Migration migration, Instance instance) { ProjectHistoryStep historyStep = new ProjectHistoryStep(); historyStep.Description = string.Format("Applying migration {0} ({1}) on instance {2}.", migration.Id, migration.Description, instance.FullName); historyStep.At = clock.Now; historyStep.By = appContext.FullUserName; historyStep.Project = migration.AuditProject; historyStep.Create(); Execution execution = new Execution(); execution.At = clock.Now; execution.By = appContext.FullUserName; execution.Migration = migration; execution.Instance = instance; execution.ExecutionState = ExecutionState.Pending; execution.AppendLog("Starting migration {0}({1}) on {2}...", migration.Id, migration.Description, instance.FullName); execution.CreateAndFlush(); try { migrationTablesManager.CheckAndCreateMigrationTable(instance, execution); execution.UpdateAndFlush(); if (!migrationTablesManager.IsMigrationAlreadyApplied(migration, instance, execution)) { ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object arg) { SyncApplyMigration(migration, instance, execution); })); } else { execution.ExecutionState = ExecutionState.Completed; execution.UpdateAndFlush(); } } catch (Exception ex) { execution.AppendLogException(ex); execution.UpdateAndFlush(); } return execution; }
private void SyncRollbackMigration(Migration migration, Instance instance, Execution execution) { try { string rollbackScript = migrationTablesManager.GetRollbackstring(migration, instance, execution); if (string.IsNullOrEmpty(rollbackScript)) { execution.AppendLog("Impossible to rollback! Aborting..."); execution.ExecutionState = ExecutionState.OnError; return; } execution.AppendLog(string.Concat(Environment.NewLine, rollbackScript, Environment.NewLine)); execution.UpdateAndFlush(); execution.AppendLog("Rollbacking..."); execution.UpdateAndFlush(); using (SqlConnection conn = new SqlConnection(connectionStringProvider.GetConnectionString(instance))) { conn.Open(); conn.InfoMessage += new SqlInfoMessageEventHandler(delegate(object sender, SqlInfoMessageEventArgs e) { execution.AppendLog(e.Message); execution.UpdateAndFlush(); }); using (System.Transactions.TransactionScope transaction = new System.Transactions.TransactionScope()) { List<string> sqlStatements = GetSqlStatements(rollbackScript); foreach (string statement in sqlStatements) { using (SqlCommand cmd = new SqlCommand(statement, conn)) { cmd.ExecuteNonQuery(); } } execution.AppendLog("Scripts completed. Deleting migration entry..."); execution.UpdateAndFlush(); migrationTablesManager.DeleteSuccessfullRollback(migration, conn); transaction.Complete(); } } execution.AppendLog("Rollback ended with success!"); execution.ExecutionState = ExecutionState.Completed; execution.UpdateAndFlush(); } catch (Exception ex) { execution.AppendLogException(ex); execution.UpdateAndFlush(); } }
private void SyncApplyMigration(Migration migration, Instance instance, Execution execution) { try { execution.AppendLog("Generating rollback scripts..."); execution.UpdateAndFlush(); string rollbackScript = scriptsGenerator.GenerateRollbackScript(migration, instance); execution.AppendLog(string.Concat(Environment.NewLine, rollbackScript, Environment.NewLine)); execution.UpdateAndFlush(); execution.AppendLog("Generating migrate scripts..."); execution.UpdateAndFlush(); string migrateScript = scriptsGenerator.GenerateMigrateScript(migration, instance); execution.AppendLog(string.Concat(Environment.NewLine, migrateScript, Environment.NewLine)); execution.UpdateAndFlush(); execution.AppendLog("Migrating..."); execution.UpdateAndFlush(); using (SqlConnection conn = new SqlConnection(connectionStringProvider.GetConnectionString(instance))) { conn.Open(); conn.InfoMessage += new SqlInfoMessageEventHandler(delegate(object sender, SqlInfoMessageEventArgs e) { execution.AppendLog(e.Message); execution.UpdateAndFlush(); }); using (System.Transactions.TransactionScope transaction = new System.Transactions.TransactionScope()) { List<string> sqlStatements = GetSqlStatements(migrateScript); foreach (string statement in sqlStatements) { using (SqlCommand cmd = new SqlCommand(statement, conn)) { cmd.ExecuteNonQuery(); } } execution.AppendLog("Scripts completed. Writing migration audit..."); execution.UpdateAndFlush(); DBAppliedMigration appliedMigration = new DBAppliedMigration(execution); appliedMigration.MigrateScript = migrateScript; appliedMigration.RollbackScript = rollbackScript; migrationTablesManager.WriteSuccessfullMigration(appliedMigration, conn); transaction.Complete(); } } execution.AppendLog("Migration ended with success!"); execution.ExecutionState = ExecutionState.Completed; execution.UpdateAndFlush(); } catch (Exception ex) { execution.AppendLogException(ex); execution.UpdateAndFlush(); } }
public bool IsMigrationAlreadyApplied(Migration migration, Instance instance, Execution currentExecution) { currentExecution.AppendLog("Is migration {0} already applied on {1} ? ...", migration.Id, instance.FullName); bool returnValue = true; using (SqlConnection connection = new SqlConnection(connectionStringProvider.GetConnectionString(instance))) { connection.Open(); using (SqlCommand cmd = new SqlCommand(@"SELECT COUNT(*) FROM [DBAppliedMigrations] WHERE [Migration_id]=@migrationId", connection)) { cmd.Parameters.Add(new SqlParameter("migrationId", migration.Id)); int applied = (int)cmd.ExecuteScalar(); if (applied == 0) { currentExecution.AppendLog("Migration {0} has never been applied on {1}.", migration.Id, instance.FullName); returnValue = false; } else { currentExecution.AppendLog("Migration {0} has already been applied on {1}.", migration.Id, instance.FullName); } } } return returnValue; }
public string GetRollbackstring(Migration migration, Instance instance, Execution currentExecution) { currentExecution.AppendLog("Retreiving rollback script ..."); string returnValue = null; using (SqlConnection connection = new SqlConnection(connectionStringProvider.GetConnectionString(instance))) { connection.Open(); using (SqlCommand cmd = new SqlCommand(@"SELECT [RollbackScript] FROM [DBAppliedMigrations] WHERE [Migration_id]=@migrationId", connection)) { cmd.Parameters.Add(new SqlParameter("migrationId", migration.Id)); returnValue = (string)cmd.ExecuteScalar(); } } return returnValue; }