public void GetMigrationsTo(long timestamp, Predicate<IMigrationMetadata> migrationSelector, out IEnumerable<ApplicableMigration> applicableMigrations, out IEnumerable<IMigrationMetadata> unidentifiedMigrations) { IEnumerable<ImportedMigration> moduleMigrations = _importedMigrations.Where(m => migrationSelector(m.Metadata)); var comparer = new MigrationMetadataComparer(); var applicableUpMigrations = new List<ApplicableMigration>( moduleMigrations.Where(m => m.Metadata.Timestamp <= timestamp && !_executedMigrations.Any(x => comparer.Equals(x, m.Metadata))) .OrderBy(m => m.Metadata.Timestamp) .Select(m => new ApplicableMigration(m, MigrationDirection.Up))); var applicableDownMigrations = new List<ApplicableMigration>( moduleMigrations.Where(m => m.Metadata.Timestamp > timestamp && _executedMigrations.Any(x => comparer.Equals(x, m.Metadata))) .OrderByDescending(m => m.Metadata.Timestamp) .Select(m => new ApplicableMigration(m, MigrationDirection.Down))); if (applicableDownMigrations.Any(m => !(m.Migration.Implementation is IReversibleMigration))) { throw new IrreversibleMigrationException(); } int countUp = applicableUpMigrations.Count; int countDown = applicableDownMigrations.Count; Log.Info("Found {0} (up: {1}, down: {2}) applicable migration(s)", countUp + countDown, countUp, countDown); applicableMigrations = applicableDownMigrations.Concat(applicableUpMigrations); // order matters! unidentifiedMigrations = new List<IMigrationMetadata>( from m in _executedMigrations where !_importedMigrations.Any(a => a.Metadata.ModuleName == m.ModuleName && a.Metadata.Timestamp == m.Timestamp) orderby m.Timestamp select m); if (unidentifiedMigrations.Any()) { Log.Warning("Found {0} migration(s) that were executed in the database but are not contained in the application.", unidentifiedMigrations.Count()); } }
private bool IsApplicable(IMigrationMetadata migration) { var comparer = new MigrationMetadataComparer(); return _applicableMigrations.Select(m => m.Migration.Metadata).Contains(migration, comparer); }