/// <summary> /// Instantiate and execute a single migration /// </summary> /// <param name="direction">Diretion to run the migration in</param> /// <param name="migrationData"><see cref="MigrationData"/> describing to migration to instantiate and execute</param> /// <param name="connection">Connection to use to execute the migration</param> protected virtual void RunMigration(MigrationDirection direction, MigrationData migrationData, TConnection connection) { var migration = this.CreateMigration(migrationData); var data = new MigrationRunData <TConnection>(connection, this.Logger ?? NullLogger.Instance, direction); migration.RunMigration(data); }
/// <summary> /// Set this.Migrations, by scanning this.migrationAssembly for migrations /// </summary> protected virtual void FindAndSetMigrations() { var migrations = (from type in this.MigrationAssembly.GetTypes() let attribute = type.GetCustomAttribute <MigrationAttribute>() where attribute != null orderby attribute.Version select new MigrationData(attribute.Version, attribute.Description, type, attribute.UseTransaction)).ToList(); if (!migrations.Any()) { throw new MigrationException("Could not find any migrations in the assembly you listed. Migrations must be decorated with [Migration]"); } if (migrations.Any(x => !typeof(TMigrationBase).IsAssignableFrom(x.Type))) { throw new MigrationException(String.Format("All migrations must derive from / implement {0}", typeof(TMigrationBase).Name)); } if (migrations.Any(x => x.Version <= 0)) { throw new MigrationException("Migrations must all have a version > 0"); } var versionLookup = migrations.ToLookup(x => x.Version); var firstDuplicate = versionLookup.FirstOrDefault(x => x.Count() > 1); if (firstDuplicate != null) { throw new MigrationException(String.Format("Found more than one migration with version {0}", firstDuplicate.Key)); } var initialMigration = new MigrationData(0, "Empty Schema", null, false); this.Migrations = new[] { initialMigration }.Concat(migrations).ToList().AsReadOnly(); }
/// <summary> /// Create and configure an instance of a migration /// </summary> /// <param name="migrationData">Data to create the migration for</param> /// <returns>An instantiated and configured migration</returns> protected virtual TMigrationBase CreateMigration(MigrationData migrationData) { var instance = (TMigrationBase)Activator.CreateInstance(migrationData.Type); instance.DB = this.ConnectionProvider.Connection; instance.Logger = this.NotNullLogger; return(instance); }
/// <summary> /// Perform a single migration /// </summary> /// <param name="oldMigration">Migration to migrate from</param> /// <param name="newMigration">Migration to migrate to</param> /// <param name="direction">Direction of the migration</param> protected virtual void MigrateStep(MigrationData oldMigration, MigrationData newMigration, MigrationDirection direction) { var migrationToRun = direction == MigrationDirection.Up ? newMigration : oldMigration; try { if (migrationToRun.UseTransaction) { this.ConnectionProvider.BeginTransaction(); } var migration = this.CreateMigration(migrationToRun); this.NotNullLogger.BeginMigration(migrationToRun, direction); if (direction == MigrationDirection.Up) { migration.Up(); } else { migration.Down(); } this.VersionProvider.UpdateVersion(this.ConnectionProvider.Connection, oldMigration.Version, newMigration.Version, newMigration.FullName); this.NotNullLogger.EndMigration(migrationToRun, direction); if (migrationToRun.UseTransaction) { this.ConnectionProvider.CommitTransaction(); } this.CurrentMigration = newMigration; } catch (Exception e) { if (migrationToRun.UseTransaction) { this.ConnectionProvider.RollbackTransaction(); } this.NotNullLogger.EndMigrationWithError(e, migrationToRun, direction); throw; } }
/// <summary> /// Create and configure an instance of a migration /// </summary> /// <param name="migrationData">Data to create the migration for</param> /// <returns>An instantiated and configured migration</returns> protected virtual TMigrationBase CreateMigration(MigrationData migrationData) { if (migrationData == null) { throw new ArgumentNullException(nameof(migrationData)); } TMigrationBase instance; try { instance = (TMigrationBase)Activator.CreateInstance(migrationData.TypeInfo.AsType()); } catch (Exception e) { throw new MigrationException($"Unable to create migration {migrationData.FullName}", e); } return(instance); }
public void EndMigration(MigrationData migration, MigrationDirection direction) { }
public void BeginMigration(MigrationData migration, MigrationDirection direction) { }
/// <summary> /// Instantiate and execute a single migration /// </summary> /// <param name="direction">Diretion to run the migration in</param> /// <param name="migrationData"><see cref="MigrationData"/> describing to migration to instantiate and execute</param> /// <param name="connection">Connection to use to execute the migration</param> protected virtual void RunMigration(MigrationDirection direction, MigrationData migrationData, TConnection connection) { var migration = this.CreateMigration(migrationData); migration.Execute(connection, this.Logger ?? NullLogger.Instance, direction); }
public void EndSequence(MigrationData from, MigrationData to) { }
/// <summary> /// Invoked when an individual migration is started /// </summary> /// <param name="migration">Migration being started</param> /// <param name="direction">Direction of the migration</param> public void BeginMigration(MigrationData migration, MigrationDirection direction) { var term = direction == MigrationDirection.Up ? "migrating" : "reverting"; this.WriteHeader($"{this.name}: {migration.Version}: {migration.FullName} {term}"); }
/// <summary> /// Invoked when a sequence of migrations fails with an error /// </summary> /// <param name="exception">Exception which was encountered</param> /// <param name="from">Migration which was migrated from</param> /// <param name="currentVersion">Last successful migration which was applied</param> public void EndSequenceWithError(Exception exception, MigrationData from, MigrationData currentVersion) { TestContext.WriteLine($"{this.name}:"); TestContext.WriteLine($"{this.name}: ERROR: {exception.Message}. Database is currently on version {currentVersion.Version}: {currentVersion.FullName}"); }
/// <summary> /// Invoked when a sequence of migrations is completed successfully /// </summary> /// <param name="from">Migration which was migrated from</param> /// <param name="to">Migration which was migrated to</param> public void EndSequence(MigrationData from, MigrationData to) { this.WriteHeader($"{this.name}: Done"); }
/// <summary> /// Invoked when a sequence of migrations is started /// </summary> /// <param name="from">Migration being migrated from</param> /// <param name="to">Migration being migrated to</param> public void BeginSequence(MigrationData from, MigrationData to) { this.WriteHeader($"{this.name}: Migrating from {from.Version}: {from.FullName} to {to.Version}: {to.FullName}"); }
public void BeginSequence(MigrationData from, MigrationData to) { }
public void EndMigrationWithError(Exception exception, MigrationData migration, MigrationDirection direction) { }
/// <summary> /// Invoked when an individual migration is completed successfully /// </summary> /// <param name="migration">Migration which completed</param> /// <param name="direction">Direction of the migration</param> public void EndMigration(MigrationData migration, MigrationDirection direction) { TestContext.WriteLine($"{this.name}:"); }
public void EndSequenceWithError(Exception exception, MigrationData from, MigrationData currentVersion) { }
/// <summary> /// Invoked when an individual migration fails with an error /// </summary> /// <param name="exception">Exception which was encountered</param> /// <param name="migration">Migration which failed</param> /// <param name="direction">Direction of the migration</param> public void EndMigrationWithError(Exception exception, MigrationData migration, MigrationDirection direction) { this.WriteError($"{this.name}: {migration.Version}: {migration.FullName} ERROR {exception.Message}"); }
/// <summary> /// Initialises a new instance of the <see cref="MigrationDataPair"/> structure /// </summary> /// <param name="from"><see cref="MigrationData"/> this migration goes from</param> /// <param name="to"><see cref="MigrationData"/> this migration goes to</param> public MigrationDataPair(MigrationData from, MigrationData to) { this.From = from; this.To = to; }