Webiant Logo Webiant Logo
  1. No results found.

    Try your search with a different keyword or use * as a wildcard.

MigrationManager.cs

using System.Reflection;
using FluentMigrator;
using FluentMigrator.Infrastructure;
using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization;

namespace Nop.Data.Migrations;

/// 
/// Represents the migration manager
/// 
public partial class MigrationManager : IMigrationManager
{
    #region Fields

    protected readonly IFilteringMigrationSource _filteringMigrationSource;
    protected readonly IMigrationRunner _migrationRunner;
    protected readonly IMigrationRunnerConventions _migrationRunnerConventions;
    protected readonly Lazy _versionLoader;

    #endregion

    #region Ctor

    public MigrationManager(
        IFilteringMigrationSource filteringMigrationSource,
        IMigrationRunner migrationRunner,
        IMigrationRunnerConventions migrationRunnerConventions,
        Lazy versionLoader)
    {
        _versionLoader = versionLoader;

        _filteringMigrationSource = filteringMigrationSource;
        _migrationRunner = migrationRunner;
        _migrationRunnerConventions = migrationRunnerConventions;
    }

    #endregion

    #region Utilities

    /// 
    /// Returns the instances for found types implementing FluentMigrator.IMigration which ready to Up or Down process (depends on isApplied parameter)
    /// 
    /// Assembly to find migrations
    /// Indicate whether to found exactly specified migration process type; if it set to true, you should set the migrationProcessType parameter to different of NoMatter
    /// Type of migration process; pass MigrationProcessType.NoMatter to load all migrations
    /// A value indicating whether to select those migrations that have been applied
    /// Indicate whether to found only schema migration; if set to true will by returns only that migrations which has the IsSchemaMigration property set to true
    /// The instances for found types implementing FluentMigrator.IMigration
    protected virtual IEnumerable GetMigrations(Assembly assembly, bool exactlyProcessType,
        MigrationProcessType migrationProcessType = MigrationProcessType.NoMatter, bool isApplied = false, bool isSchemaMigration = false)
    {
        if (exactlyProcessType && migrationProcessType == MigrationProcessType.NoMatter)
            throw new ArgumentException("Migration process type can't be NoMatter if exactlyProcessType set to true", nameof(migrationProcessType));

        //load all version data stored in the version table
        //we do this for avoid a problem with state of migration
        _versionLoader.Value.LoadVersionInfo();

        var migrations = _filteringMigrationSource
            .GetMigrations(t =>
            {
                var migrationAttribute = t.GetCustomAttribute();

                if (migrationAttribute is null)
                    return false;

                if (isSchemaMigration && !migrationAttribute.IsSchemaMigration)
                    return false;

                if (isApplied == !_versionLoader.Value.VersionInfo.HasAppliedMigration(migrationAttribute.Version))
                    return false;

                if (exactlyProcessType && migrationProcessType != migrationAttribute.TargetMigrationProcess)
                    return false;

                if (migrationAttribute.TargetMigrationProcess != MigrationProcessType.NoMatter &&
                    migrationProcessType != MigrationProcessType.NoMatter &&
                    migrationProcessType != migrationAttribute.TargetMigrationProcess)
                    return false;

                return assembly == null || t.Assembly == assembly;
            }) ?? Enumerable.Empty();

        return migrations.Select(_migrationRunnerConventions.GetMigrationInfoForMigration);
    }

    #endregion

    #region Methods

    /// 
    /// Executes an Up for all found unapplied migrations
    /// 
    /// Assembly to find migrations
    /// Type of migration process
    /// Commit only version information
    public virtual void ApplyUpMigrations(Assembly assembly, MigrationProcessType migrationProcessType = MigrationProcessType.Installation, bool commitVersionOnly = false)
    {
        ArgumentNullException.ThrowIfNull(assembly);

        foreach (var migrationInfo in GetMigrations(assembly, commitVersionOnly && migrationProcessType != MigrationProcessType.NoMatter, migrationProcessType).OrderBy(migration => migration.Version))
            ApplyUpMigration(migrationInfo, commitVersionOnly);
    }

    /// 
    /// Executes an Up for schema unapplied migrations
    /// 
    /// Assembly to find migrations
    public virtual void ApplyUpSchemaMigrations(Assembly assembly)
    {
        ArgumentNullException.ThrowIfNull(assembly);

        foreach (var migrationInfo in GetMigrations(assembly, false, MigrationProcessType.NoMatter, isSchemaMigration: true).OrderBy(migration => migration.Version))
            ApplyUpMigration(migrationInfo);
    }

    /// 
    /// Executes a Down for all found (and applied) migrations
    /// 
    /// Assembly to find the migration
    public void ApplyDownMigrations(Assembly assembly)
    {
        ArgumentNullException.ThrowIfNull(assembly);

        foreach (var migrationInfo in GetMigrations(assembly, false, MigrationProcessType.NoMatter, true).OrderByDescending(migration => migration.Version))
            ApplyDownMigration(migrationInfo);
    }

    /// 
    /// Executes down expressions for the passed migration
    /// 
    /// Migration to rollback
    public void ApplyDownMigration(IMigrationInfo migrationInfo)
    {
        ArgumentNullException.ThrowIfNull(migrationInfo);

        _migrationRunner.Down(migrationInfo.Migration);
        _versionLoader.Value.DeleteVersion(migrationInfo.Version);
    }

    /// 
    /// Executes up expressions for the passed migration
    /// 
    /// Migration to apply
    /// Commit only version information
    public void ApplyUpMigration(IMigrationInfo migrationInfo, bool commitVersionOnly = false)
    {
        ArgumentNullException.ThrowIfNull(migrationInfo);

        if (!commitVersionOnly)
            _migrationRunner.Up(migrationInfo.Migration);
#if DEBUG
        if (!migrationInfo.IsNeedToApplyInDbOnDebugMode())
            return;
#endif
        _versionLoader.Value
            .UpdateVersionInfo(migrationInfo.Version, migrationInfo.Description ?? migrationInfo.Migration.GetType().Name);
    }

    #endregion
}