public IEnumerable <VersionedMigration> GetMigrations(MigrationVersion after, MigrationVersion before)
        {
            if (!string.Equals(after.Collection, before.Collection))
            {
                throw new ArgumentException("Cannot apply cross collections migrations");
            }

            var migrations =
                (
                    from type in LocatedAssembly.GetTypes()
                    where typeof(IMigration).GetTypeInfo().IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract
                    let attribute = type.GetTypeInfo().GetCustomAttribute <MigrationAttribute>()
                                    where attribute != null &&
                                    (string.IsNullOrEmpty(after.Collection) || string.Equals(attribute.Collection, after.Collection)) &&
                                    after.Version < attribute.Version && attribute.Version <= before.Version
                                    select new { Migration = _factory.Create(type), Version = new MigrationVersion(attribute.Collection, attribute.Version, attribute.Description) }
                ).ToList();

            foreach (var m in migrations)
            {
                ((IDbMigration)m.Migration).UseDatabase(_database);
            }

            return(migrations.Select(x => new VersionedMigration(x.Migration, x.Version)));
        }
        public void Apply <T>()
        {
            lock (_lock)
            {
                using (var log = logFactory.Create())
                {
                    var migrations = migrationFactory.Create(
                        locator.LocateAll <T>().Where(r => HasForceAttribute(r) || !log.IsCommited(r)));

                    foreach (var m in migrations)
                    {
                        var commitToLog = ShouldCommitToLog(log, m);

                        Serilog.Log
                        .ForContext("CommitToLog", commitToLog)
                        .Information("Migrations: Applying {MigrationName}", m.GetType().Name);
                        m.Apply();

                        if (commitToLog)
                        {
                            log.Commit(m);
                        }
                    }
                }
            }

            bool ShouldCommitToLog(IMigrationLog log, Migration m)
            {
                var type = m.GetType();

                if (HasDoNotCommitAttribute(type))
                {
                    return(false);
                }

                if (log.IsCommited(type))
                {
                    return(false);
                }

                return(true);
            }

            bool HasDoNotCommitAttribute(Type migration)
            {
                return(migration.CustomAttributes.FirstOrDefault(r => r.AttributeType == typeof(DoNotCommitAttribute)) != null);
            }

            bool HasForceAttribute(Type migration)
            {
                return(migration.CustomAttributes.FirstOrDefault(r => r.AttributeType == typeof(ForceMigrationAttribute)) != null);
            }
        }
        public IEnumerable <VersionedMigration> GetMigrations(MigrationVersion after, MigrationVersion before)
        {
            var migrations =
                (
                    from type in _assembly.GetTypes()
                    where typeof(IMigration).GetTypeInfo().IsAssignableFrom(type) && !type.GetTypeInfo().IsAbstract
                    let attribute = type.GetTypeInfo().GetCustomAttribute <MigrationAttribute>()
                                    where attribute != null && after.Version < attribute.Version && attribute.Version <= before.Version
                                    orderby attribute.Version
                                    select new { Migration = _factory.Create(type), Version = new MigrationVersion(attribute.Version, attribute.Description) }
                ).ToList();

            foreach (var m in migrations)
            {
                ((IDbMigration)m.Migration).UseDatabase(_database);
            }

            return(migrations.Select(x => new VersionedMigration(x.Migration, x.Version)));
        }