178 lines
5.6 KiB
C#
178 lines
5.6 KiB
C#
|
#region License
|
||
|
|
||
|
//The contents of this file are subject to the Mozilla Public License
|
||
|
//Version 1.1 (the "License"); you may not use this file except in
|
||
|
//compliance with the License. You may obtain a copy of the License at
|
||
|
//http://www.mozilla.org/MPL/
|
||
|
//Software distributed under the License is distributed on an "AS IS"
|
||
|
//basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||
|
//License for the specific language governing rights and limitations
|
||
|
//under the License.
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Reflection;
|
||
|
using Migrator.Framework;
|
||
|
using Migrator.Framework.Loggers;
|
||
|
|
||
|
namespace Migrator
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// Migrations mediator.
|
||
|
/// </summary>
|
||
|
public class Migrator
|
||
|
{
|
||
|
private readonly ITransformationProvider _provider;
|
||
|
|
||
|
private readonly MigrationLoader _migrationLoader;
|
||
|
|
||
|
private ILogger _logger = new Logger(false);
|
||
|
protected bool _dryrun;
|
||
|
private string[] _args;
|
||
|
|
||
|
public string[] args
|
||
|
{
|
||
|
get { return _args; }
|
||
|
set { _args = value; }
|
||
|
}
|
||
|
|
||
|
public Migrator(string provider, string connectionString, Assembly migrationAssembly)
|
||
|
: this(provider, connectionString, migrationAssembly, false)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public Migrator(string provider, string connectionString, Assembly migrationAssembly, bool trace)
|
||
|
: this(ProviderFactory.Create(provider, connectionString), migrationAssembly, trace)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public Migrator(string provider, string connectionString, Assembly migrationAssembly, bool trace, ILogger logger)
|
||
|
: this(ProviderFactory.Create(provider, connectionString), migrationAssembly, trace, logger)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public Migrator(ITransformationProvider provider, Assembly migrationAssembly, bool trace)
|
||
|
: this(provider, migrationAssembly, trace, new Logger(trace, new ConsoleWriter()))
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public Migrator(ITransformationProvider provider, Assembly migrationAssembly, bool trace, ILogger logger)
|
||
|
{
|
||
|
_provider = provider;
|
||
|
Logger = logger;
|
||
|
|
||
|
_migrationLoader = new MigrationLoader(provider, migrationAssembly, trace);
|
||
|
_migrationLoader.CheckForDuplicatedVersion();
|
||
|
}
|
||
|
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns registered migration <see cref="System.Type">types</see>.
|
||
|
/// </summary>
|
||
|
public List<Type> MigrationsTypes
|
||
|
{
|
||
|
get { return _migrationLoader.MigrationsTypes; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Run all migrations up to the latest. Make no changes to database if
|
||
|
/// dryrun is true.
|
||
|
/// </summary>
|
||
|
public void MigrateToLastVersion()
|
||
|
{
|
||
|
MigrateTo(_migrationLoader.LastVersion);
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Returns the current migrations applied to the database.
|
||
|
/// </summary>
|
||
|
public List<long> AppliedMigrations
|
||
|
{
|
||
|
get { return _provider.AppliedMigrations; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Get or set the event logger.
|
||
|
/// </summary>
|
||
|
public ILogger Logger
|
||
|
{
|
||
|
get { return _logger; }
|
||
|
set
|
||
|
{
|
||
|
_logger = value;
|
||
|
_provider.Logger = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public virtual bool DryRun
|
||
|
{
|
||
|
get { return _dryrun; }
|
||
|
set { _dryrun = value; }
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Migrate the database to a specific version.
|
||
|
/// Runs all migration between the actual version and the
|
||
|
/// specified version.
|
||
|
/// If <c>version</c> is greater then the current version,
|
||
|
/// the <c>Up()</c> method will be invoked.
|
||
|
/// If <c>version</c> lower then the current version,
|
||
|
/// the <c>Down()</c> method of previous migration will be invoked.
|
||
|
/// If <c>dryrun</c> is set, don't write any changes to the database.
|
||
|
/// </summary>
|
||
|
/// <param name="version">The version that must became the current one</param>
|
||
|
public void MigrateTo(long version)
|
||
|
{
|
||
|
|
||
|
if (_migrationLoader.MigrationsTypes.Count == 0)
|
||
|
{
|
||
|
_logger.Warn("No public classes with the Migration attribute were found.");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool firstRun = true;
|
||
|
BaseMigrate migrate = BaseMigrate.GetInstance(_migrationLoader.GetAvailableMigrations(), _provider, _logger);
|
||
|
migrate.DryRun = DryRun;
|
||
|
Logger.Started(migrate.AppliedVersions, version);
|
||
|
|
||
|
while (migrate.Continue(version))
|
||
|
{
|
||
|
IMigration migration = _migrationLoader.GetMigration(migrate.Current);
|
||
|
if (null == migration)
|
||
|
{
|
||
|
_logger.Skipping(migrate.Current);
|
||
|
migrate.Iterate();
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
try
|
||
|
{
|
||
|
if (firstRun)
|
||
|
{
|
||
|
migration.InitializeOnce(_args);
|
||
|
firstRun = false;
|
||
|
}
|
||
|
|
||
|
migrate.Migrate(migration);
|
||
|
}
|
||
|
catch (Exception ex)
|
||
|
{
|
||
|
Logger.Exception(migrate.Current, migration.Name, ex);
|
||
|
|
||
|
// Oho! error! We rollback changes.
|
||
|
Logger.RollingBack(migrate.Previous);
|
||
|
_provider.Rollback();
|
||
|
|
||
|
throw;
|
||
|
}
|
||
|
|
||
|
migrate.Iterate();
|
||
|
}
|
||
|
|
||
|
Logger.Finished(migrate.AppliedVersions, version);
|
||
|
}
|
||
|
}
|
||
|
}
|