diff --git a/Migrator-vs2010.sln b/Migrator-vs2010.sln index a0c0e945..5f03a6c7 100644 --- a/Migrator-vs2010.sln +++ b/Migrator-vs2010.sln @@ -1,81 +1,49 @@ - -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Runners", "Runners", "{1CC77E58-4B1E-4D3F-86EA-5078883434FC}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{9844714F-717A-4C16-97A9-9995BB1B4A8B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{8FF5F3DF-DF83-470C-ADFE-C0FF2B858F0F}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extras", "Extras", "{02B014BC-CC35-466F-A2F4-C5B5AC830653}" - ProjectSection(SolutionItems) = preProject - doc\CHANGES.txt = doc\CHANGES.txt - default.build = default.build - local.properties-example = local.properties-example - src\MigratorDotNet.snk = src\MigratorDotNet.snk - doc\README.txt = doc\README.txt - doc\TODO.txt = doc\TODO.txt - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator-vs2010", "src\Migrator\Migrator-vs2010.csproj", "{1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Framework-vs2010", "src\Migrator.Framework\Migrator.Framework-vs2010.csproj", "{5270F048-E580-486C-B14C-E5B9F6E539D4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Providers-vs2010", "src\Migrator.Providers\Migrator.Providers-vs2010.csproj", "{D58C68E4-D789-40F7-9078-C9F587D4363C}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Console-vs2010", "src\Migrator.Console\Migrator.Console-vs2010.csproj", "{FBE3A83A-D0F8-4D72-AF8D-9EF772569A31}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.MSBuild-vs2010", "src\Migrator.MSBuild\Migrator.MSBuild-vs2010.csproj", "{A145FFA9-5FE6-4636-93B8-0C110D132BF3}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.NAnt-vs2010", "src\Migrator.NAnt\Migrator.NAnt-vs2010.csproj", "{CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Tests-vs2010", "src\Migrator.Tests\Migrator.Tests-vs2010.csproj", "{882B6A93-67B8-45BF-8636-5796B1B1CBF8}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Release|Any CPU.Build.0 = Release|Any CPU - {5270F048-E580-486C-B14C-E5B9F6E539D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5270F048-E580-486C-B14C-E5B9F6E539D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5270F048-E580-486C-B14C-E5B9F6E539D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5270F048-E580-486C-B14C-E5B9F6E539D4}.Release|Any CPU.Build.0 = Release|Any CPU - {D58C68E4-D789-40F7-9078-C9F587D4363C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D58C68E4-D789-40F7-9078-C9F587D4363C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D58C68E4-D789-40F7-9078-C9F587D4363C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D58C68E4-D789-40F7-9078-C9F587D4363C}.Release|Any CPU.Build.0 = Release|Any CPU - {FBE3A83A-D0F8-4D72-AF8D-9EF772569A31}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FBE3A83A-D0F8-4D72-AF8D-9EF772569A31}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBE3A83A-D0F8-4D72-AF8D-9EF772569A31}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FBE3A83A-D0F8-4D72-AF8D-9EF772569A31}.Release|Any CPU.Build.0 = Release|Any CPU - {A145FFA9-5FE6-4636-93B8-0C110D132BF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A145FFA9-5FE6-4636-93B8-0C110D132BF3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A145FFA9-5FE6-4636-93B8-0C110D132BF3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A145FFA9-5FE6-4636-93B8-0C110D132BF3}.Release|Any CPU.Build.0 = Release|Any CPU - {CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101}.Release|Any CPU.Build.0 = Release|Any CPU - {882B6A93-67B8-45BF-8636-5796B1B1CBF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {882B6A93-67B8-45BF-8636-5796B1B1CBF8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {882B6A93-67B8-45BF-8636-5796B1B1CBF8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {882B6A93-67B8-45BF-8636-5796B1B1CBF8}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {FBE3A83A-D0F8-4D72-AF8D-9EF772569A31} = {1CC77E58-4B1E-4D3F-86EA-5078883434FC} - {A145FFA9-5FE6-4636-93B8-0C110D132BF3} = {1CC77E58-4B1E-4D3F-86EA-5078883434FC} - {CDD39DB7-C9C0-4ECA-AD36-1B4D0BF59101} = {1CC77E58-4B1E-4D3F-86EA-5078883434FC} - {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} - {5270F048-E580-486C-B14C-E5B9F6E539D4} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} - {D58C68E4-D789-40F7-9078-C9F587D4363C} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} - {882B6A93-67B8-45BF-8636-5796B1B1CBF8} = {8FF5F3DF-DF83-470C-ADFE-C0FF2B858F0F} - EndGlobalSection -EndGlobal + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{9844714F-717A-4C16-97A9-9995BB1B4A8B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extras", "Extras", "{02B014BC-CC35-466F-A2F4-C5B5AC830653}" + ProjectSection(SolutionItems) = preProject + doc\CHANGES.txt = doc\CHANGES.txt + default.build = default.build + local.properties-example = local.properties-example + src\MigratorDotNet.snk = src\MigratorDotNet.snk + doc\README.txt = doc\README.txt + doc\TODO.txt = doc\TODO.txt + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator-vs2010", "src\Migrator\Migrator-vs2010.csproj", "{1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Framework-vs2010", "src\Migrator.Framework\Migrator.Framework-vs2010.csproj", "{5270F048-E580-486C-B14C-E5B9F6E539D4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Migrator.Providers-vs2010", "src\Migrator.Providers\Migrator.Providers-vs2010.csproj", "{D58C68E4-D789-40F7-9078-C9F587D4363C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D}.Release|Any CPU.Build.0 = Release|Any CPU + {5270F048-E580-486C-B14C-E5B9F6E539D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5270F048-E580-486C-B14C-E5B9F6E539D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5270F048-E580-486C-B14C-E5B9F6E539D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5270F048-E580-486C-B14C-E5B9F6E539D4}.Release|Any CPU.Build.0 = Release|Any CPU + {D58C68E4-D789-40F7-9078-C9F587D4363C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D58C68E4-D789-40F7-9078-C9F587D4363C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D58C68E4-D789-40F7-9078-C9F587D4363C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D58C68E4-D789-40F7-9078-C9F587D4363C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {1FEE70A4-AAD7-4C60-BE60-3F7DC03A8C4D} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} + {5270F048-E580-486C-B14C-E5B9F6E539D4} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} + {D58C68E4-D789-40F7-9078-C9F587D4363C} = {9844714F-717A-4C16-97A9-9995BB1B4A8B} + EndGlobalSection +EndGlobal diff --git a/src/Migrator.Framework/ITransformationProvider.cs b/src/Migrator.Framework/ITransformationProvider.cs index 46d77199..11f4c5a9 100644 --- a/src/Migrator.Framework/ITransformationProvider.cs +++ b/src/Migrator.Framework/ITransformationProvider.cs @@ -17,8 +17,8 @@ public interface ITransformationProvider : IDisposable /// /// The list of Migrations currently applied to the database. - /// - List AppliedMigrations { get; } + /// + List> AppliedMigrations { get; } ILogger Logger { get; set; } @@ -346,14 +346,16 @@ void GenerateForeignKey(string foreignTable, string foreignColumn, string primar /// /// Marks a Migration version number as having been applied /// - /// The version number of the migration that was applied - void MigrationApplied(long version); + /// The version number of the migration that was applied + /// Scope of migrations + void MigrationApplied(long version, string scope); /// /// Marks a Migration version number as having been rolled back from the database /// - /// The version number of the migration that was removed - void MigrationUnApplied(long version); + /// The version number of the migration that was removed + /// Scope of migrations + void MigrationUnApplied(long version, string scope); /// /// Remove an existing column from a table diff --git a/src/Migrator.Framework/MigrationAttribute.cs b/src/Migrator.Framework/MigrationAttribute.cs index c424dac1..2d2659d3 100644 --- a/src/Migrator.Framework/MigrationAttribute.cs +++ b/src/Migrator.Framework/MigrationAttribute.cs @@ -11,8 +11,9 @@ #endregion -using System; - +using System; +using System.Collections.Generic; + namespace Migrator.Framework { /// @@ -20,15 +21,23 @@ namespace Migrator.Framework /// public class MigrationAttribute : Attribute { + private string _scopeAssembly; private long _version; - private bool _ignore = false; - - /// - /// Describe the migration - /// - /// The unique version of the migration. - public MigrationAttribute(long version) - { + private bool _ignore = false; + + /// + /// Describe the migration + /// + /// The unique version of the migration. + /// Scope assembly + public MigrationAttribute(long version) + : this(version, null) + { + } + + public MigrationAttribute(long version, string scopeAssembly) + { + _scopeAssembly = scopeAssembly; Version = version; } @@ -41,6 +50,32 @@ public long Version private set { _version = value; } } + private string GetScopeId(Type t) + { + if (_scopeAssembly != null && _scopeAssembly.Length == 0) + return "00000000000000000000000000000000"; + var x = new System.Security.Cryptography.MD5CryptoServiceProvider(); + var bs = System.Text.Encoding.UTF8.GetBytes(_scopeAssembly ?? t.Assembly.GetName().Name); + bs = x.ComputeHash(bs); + var s = new System.Text.StringBuilder(); + foreach (var b in bs) + s.Append(b.ToString("x2").ToUpper()); + return s.ToString(); + } + + private Type _vType; + private KeyValuePair _v; + + public KeyValuePair GetVersion(Type t) + { + if (t != _vType) + { + _v = new KeyValuePair(GetScopeId(t), Version); + _vType = t; + } + return _v; + } + /// /// Set to true to ignore this migration. /// diff --git a/src/Migrator.Providers/Migrator.Providers-vs2010.csproj b/src/Migrator.Providers/Migrator.Providers-vs2010.csproj index a41a9696..9c26d9fb 100644 --- a/src/Migrator.Providers/Migrator.Providers-vs2010.csproj +++ b/src/Migrator.Providers/Migrator.Providers-vs2010.csproj @@ -1,160 +1,161 @@ - - - - Debug - AnyCPU - 9.0.30729 - 2.0 - {D58C68E4-D789-40F7-9078-C9F587D4363C} - Library - Migrator.Providers - Migrator.Providers - - - 3.5 - - - false - true - MigratorDotNet.snk - v2.0 - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - true - full - false - bin\Debug\ - TRACE;DEBUG;DOTNET2 - prompt - 4 - AllRules.ruleset - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - AllRules.ruleset - - - - False - ..\..\lib\Mono.Data.Sqlite.dll - - - False - ..\..\lib\Npgsql\net-2.0\Mono.Security.dll - - - False - ..\..\lib\MySql.Data.dll - - - False - ..\..\lib\NAnt.Core.dll - - - False - ..\..\lib\Npgsql\net-2.0\Npgsql.dll - - - False - ..\..\lib\Oracle.DataAccess.dll - - - - - False - ..\..\lib\System.Data.SQLite.DLL - - - ..\..\lib\System.Data.SqlServerCe.dll - False - - - - - - - - - - - - - - - - - - - - - - - - - - - {5270F048-E580-486C-B14C-E5B9F6E539D4} - Migrator.Framework-vs2008 - - - - - - - - False - .NET Framework 3.5 SP1 Client Profile - false - - - False - .NET Framework 2.0 %28x86%29 - true - - - False - .NET Framework 3.0 %28x86%29 - false - - - False - .NET Framework 3.5 - false - - - False - .NET Framework 3.5 SP1 - false - - - - - - + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {D58C68E4-D789-40F7-9078-C9F587D4363C} + Library + Migrator.Providers + Migrator.Providers + + + 3.5 + + + false + true + MigratorDotNet.snk + v2.0 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + full + false + bin\Debug\ + TRACE;DEBUG;DOTNET2 + prompt + 4 + AllRules.ruleset + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + AllRules.ruleset + + + + False + ..\..\lib\Mono.Data.Sqlite.dll + + + False + ..\..\lib\Npgsql\net-2.0\Mono.Security.dll + + + False + ..\..\lib\MySql.Data.dll + + + False + ..\..\lib\NAnt.Core.dll + + + False + ..\..\lib\Npgsql\net-2.0\Npgsql.dll + + + False + ..\..\lib\Oracle.DataAccess.dll + + + + + False + ..\..\lib\System.Data.SQLite.DLL + + + ..\..\lib\System.Data.SqlServerCe.dll + False + + + + + + + + + + + + + + + + + + + + + + + + + + + + {5270F048-E580-486C-B14C-E5B9F6E539D4} + Migrator.Framework-vs2008 + + + + + + + + False + .NET Framework 3.5 SP1 Client Profile + false + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + False + .NET Framework 3.5 SP1 + false + + + + + + + --> \ No newline at end of file diff --git a/src/Migrator.Providers/NoOpTransformationProvider.cs b/src/Migrator.Providers/NoOpTransformationProvider.cs index 48f66665..1c86999c 100644 --- a/src/Migrator.Providers/NoOpTransformationProvider.cs +++ b/src/Migrator.Providers/NoOpTransformationProvider.cs @@ -283,19 +283,19 @@ public ITransformationProvider this[string provider] get { return this; } } - public void MigrationApplied(long version) + public void MigrationApplied(long version, string scope = null) { //no op - } - - public void MigrationUnApplied(long version) + } + + public void MigrationUnApplied(long version, string scope = null) { //no op - } - - public List AppliedMigrations - { - get { return new List(); } + } + + public List> AppliedMigrations + { + get { return new List>(); } } protected void CreateSchemaInfoTable() diff --git a/src/Migrator.Providers/ProviderGlobalSettings.cs b/src/Migrator.Providers/ProviderGlobalSettings.cs new file mode 100644 index 00000000..d05515d4 --- /dev/null +++ b/src/Migrator.Providers/ProviderGlobalSettings.cs @@ -0,0 +1,18 @@ +namespace Migrator.Providers +{ + public class ProviderGlobalSettings + { + public static string TableSchemaInfo { get; set; } + public static string ColumnScope { get; set; } + public static string ColumnVersion { get; set; } + public static string GlobalScopeId { get; set; } + + static ProviderGlobalSettings() + { + TableSchemaInfo = "DbSchemaInfo"; + ColumnScope = "Scope"; + ColumnVersion = "Version"; + GlobalScopeId = "00000000000000000000000000000000"; + } + } +} diff --git a/src/Migrator.Providers/TransformationProvider.cs b/src/Migrator.Providers/TransformationProvider.cs index 96478074..9ef33718 100644 --- a/src/Migrator.Providers/TransformationProvider.cs +++ b/src/Migrator.Providers/TransformationProvider.cs @@ -29,8 +29,8 @@ public abstract class TransformationProvider : ITransformationProvider { private ILogger _logger; protected IDbConnection _connection; - private IDbTransaction _transaction; - private List _appliedMigrations; + private IDbTransaction _transaction; + private List> _appliedMigrations; protected readonly string _connectionString; protected Dialect _dialect; @@ -738,53 +738,75 @@ public void Commit() /// /// The list of Migrations currently applied to the database. - /// - public List AppliedMigrations + /// + public List> AppliedMigrations { get { if(_appliedMigrations == null) - { - _appliedMigrations = new List(); - CreateSchemaInfoTable(); - using(IDataReader reader = Select("version","SchemaInfo")){ + { + _appliedMigrations = new List>(); + CreateSchemaInfoTable(); + using (IDataReader reader = Select("*", ProviderGlobalSettings.TableSchemaInfo)) + { while(reader.Read()){ - _appliedMigrations.Add(Convert.ToInt64(reader.GetValue(0))); + _appliedMigrations.Add(new KeyValuePair(Convert.ToString(reader.GetValue(0)), Convert.ToInt64(reader.GetValue(1)))); } } } return _appliedMigrations; } - } - - /// - /// Marks a Migration version number as having been applied - /// - /// The version number of the migration that was applied - public void MigrationApplied(long version) - { - CreateSchemaInfoTable(); - Insert("SchemaInfo",new string[]{"version"},new string[]{version.ToString()}); - _appliedMigrations.Add(version); - } - - /// - /// Marks a Migration version number as having been rolled back from the database - /// - /// The version number of the migration that was removed - public void MigrationUnApplied(long version) - { - CreateSchemaInfoTable(); - Delete("SchemaInfo", "version", version.ToString()); - _appliedMigrations.Remove(version); + } + + /// + /// Marks a Migration version number as having been applied + /// + /// The version number of the migration that was applied + /// Scope of migrations + public void MigrationApplied(long version, string scope) + { + CreateSchemaInfoTable(); + var scopeFixed = FixScope(scope); + Insert(ProviderGlobalSettings.TableSchemaInfo, new string[] { ProviderGlobalSettings.ColumnScope, ProviderGlobalSettings.ColumnVersion }, new string[] { scopeFixed, version.ToString() }); + _appliedMigrations.Add(new KeyValuePair(scopeFixed, version)); + } + + /// + /// Marks a Migration version number as having been rolled back from the database + /// + /// The version number of the migration that was removed + /// Scope of migrations + public void MigrationUnApplied(long version, string scope) + { + CreateSchemaInfoTable(); + var scopeFixed = FixScope(scope); + Delete(ProviderGlobalSettings.TableSchemaInfo, new string[] { ProviderGlobalSettings.ColumnScope, ProviderGlobalSettings.ColumnVersion }, new string[] { scopeFixed, version.ToString() }); + KeyValuePair? toDelete = null; + foreach (var appliedMigration in _appliedMigrations) + { + if (appliedMigration.Value == version && appliedMigration.Key.CompareTo(scopeFixed) == 0) + { + toDelete = appliedMigration; + break; + } + } + if (toDelete.HasValue) + _appliedMigrations.Remove(toDelete.Value); } + private static string FixScope(string scope) + { + return (String.IsNullOrEmpty(scope) || scope.Length != 32) ? ProviderGlobalSettings.GlobalScopeId : scope; + } + protected void CreateSchemaInfoTable() { - EnsureHasConnection(); - if (!TableExists("SchemaInfo")) - { - AddTable("SchemaInfo", new Column("Version", DbType.Int64, ColumnProperty.PrimaryKey)); + EnsureHasConnection(); + if (!TableExists(ProviderGlobalSettings.TableSchemaInfo)) + { + AddTable(ProviderGlobalSettings.TableSchemaInfo, + new Column(ProviderGlobalSettings.ColumnScope, DbType.StringFixedLength, 32, ColumnProperty.Indexed), + new Column(ProviderGlobalSettings.ColumnVersion, DbType.Int64, ColumnProperty.Indexed)); } } diff --git a/src/Migrator/BaseMigrate.cs b/src/Migrator/BaseMigrate.cs index 5d1847c4..a82e6784 100644 --- a/src/Migrator/BaseMigrate.cs +++ b/src/Migrator/BaseMigrate.cs @@ -9,20 +9,28 @@ public abstract class BaseMigrate protected ILogger _logger; protected List _availableMigrations; protected List _original; + protected string _scope; protected long _current; protected bool _dryrun; - protected BaseMigrate(List availableMigrations, ITransformationProvider provider, ILogger logger) + protected BaseMigrate(string scope, List availableMigrations, ITransformationProvider provider, ILogger logger) { _provider = provider; - _availableMigrations = availableMigrations; - _original = new List (_provider.AppliedMigrations.ToArray()); //clone + _availableMigrations = availableMigrations; + _scope = scope; + _original = new List(); //clone + foreach (var appliedMigration in _provider.AppliedMigrations) + { + if (scope == appliedMigration.Key) + _original.Add(appliedMigration.Value); + } + _original.Sort(); _logger = logger; } - public static BaseMigrate GetInstance(List availableMigrations, ITransformationProvider provider, ILogger logger) + public static BaseMigrate GetInstance(string scope, List availableMigrations, ITransformationProvider provider, ILogger logger) { - return new MigrateAnywhere(availableMigrations, provider, logger); + return new MigrateAnywhere(scope, availableMigrations, provider, logger); } public List AppliedVersions @@ -65,8 +73,8 @@ protected long NextMigration() int migrationSearch = _availableMigrations.IndexOf(Current)+1; // See if we can find a migration that matches the requirement - while(migrationSearch < _availableMigrations.Count - && _provider.AppliedMigrations.Contains(_availableMigrations[migrationSearch])) + while(migrationSearch < _availableMigrations.Count + && AppliedMigrationsContains(_availableMigrations[migrationSearch])) { migrationSearch++; } @@ -91,8 +99,8 @@ protected long PreviousMigration() int migrationSearch = _availableMigrations.IndexOf(Current)-1; // See if we can find a migration that matches the requirement - while(migrationSearch > -1 - && !_provider.AppliedMigrations.Contains(_availableMigrations[migrationSearch])) + while(migrationSearch > -1 + && !AppliedMigrationsContains(_availableMigrations[migrationSearch])) { migrationSearch--; } @@ -106,5 +114,15 @@ protected long PreviousMigration() // found one. return _availableMigrations[migrationSearch]; } + + private bool AppliedMigrationsContains(long version) + { + foreach (var appliedMigration in _provider.AppliedMigrations) + { + if (appliedMigration.Key == _scope && appliedMigration.Value == version) + return true; + } + return false; + } } } diff --git a/src/Migrator/MigrateAnywhere.cs b/src/Migrator/MigrateAnywhere.cs index eb1bde01..41d257cf 100644 --- a/src/Migrator/MigrateAnywhere.cs +++ b/src/Migrator/MigrateAnywhere.cs @@ -11,12 +11,18 @@ public class MigrateAnywhere : BaseMigrate { private bool _goForward; - public MigrateAnywhere(List availableMigrations, ITransformationProvider provider, ILogger logger) - : base(availableMigrations, provider, logger) + public MigrateAnywhere(string scope, List availableMigrations, ITransformationProvider provider, ILogger logger) + : base(scope, availableMigrations, provider, logger) { _current = 0; - if (provider.AppliedMigrations.Count > 0) { - _current = provider.AppliedMigrations[provider.AppliedMigrations.Count - 1]; + if (provider.AppliedMigrations.Count > 0) { + foreach (var appliedMigration in provider.AppliedMigrations) + { + if (appliedMigration.Key != scope) + continue; + if (_current < appliedMigration.Value) + _current = appliedMigration.Value; + } } _goForward = false; } @@ -61,9 +67,20 @@ public override bool Continue(long version) public override void Migrate(IMigration migration) { _provider.BeginTransaction(); - MigrationAttribute attr = (MigrationAttribute)Attribute.GetCustomAttribute(migration.GetType(), typeof(MigrationAttribute)); - - if (_provider.AppliedMigrations.Contains(attr.Version)) { + MigrationAttribute attr = (MigrationAttribute)Attribute.GetCustomAttribute(migration.GetType(), typeof(MigrationAttribute)); + + var v = attr.GetVersion(migration.GetType()); + var contains = false; + + foreach (var appliedMigration in _provider.AppliedMigrations) + { + if (appliedMigration.Key != v.Key || appliedMigration.Value != v.Value) continue; + contains = true; + break; + } + + if (contains) + { RemoveMigration(migration, attr); } else { ApplyMigration(migration, attr); @@ -76,8 +93,9 @@ private void ApplyMigration(IMigration migration, MigrationAttribute attr) _logger.MigrateUp(Current, migration.Name); if(! DryRun) { - migration.Up(); - _provider.MigrationApplied(attr.Version); + migration.Up(); + var v = attr.GetVersion(migration.GetType()); + _provider.MigrationApplied(v.Value, v.Key); _provider.Commit(); migration.AfterUp(); } @@ -89,8 +107,9 @@ private void RemoveMigration(IMigration migration, MigrationAttribute attr) _logger.MigrateDown(Current, migration.Name); if (! DryRun) { - migration.Down(); - _provider.MigrationUnApplied(attr.Version); + migration.Down(); + var v = attr.GetVersion(migration.GetType()); + _provider.MigrationUnApplied(v.Value, v.Key); _provider.Commit(); migration.AfterDown(); } diff --git a/src/Migrator/MigrationComparer.cs b/src/Migrator/MigrationComparer.cs index a1f7281f..f85d26fc 100644 --- a/src/Migrator/MigrationComparer.cs +++ b/src/Migrator/MigrationComparer.cs @@ -30,14 +30,29 @@ public MigrationTypeComparer(bool ascending) public int Compare(Type x, Type y) { MigrationAttribute attribOfX = (MigrationAttribute) Attribute.GetCustomAttribute(x, typeof(MigrationAttribute)); - MigrationAttribute attribOfY = (MigrationAttribute) Attribute.GetCustomAttribute(y, typeof(MigrationAttribute)); - - if (_ascending) - return attribOfX.Version.CompareTo(attribOfY.Version); - else - return attribOfY.Version.CompareTo(attribOfX.Version); - - + MigrationAttribute attribOfY = (MigrationAttribute) Attribute.GetCustomAttribute(y, typeof(MigrationAttribute)); + + var vX = attribOfX.GetVersion(x); + var vY = attribOfY.GetVersion(y); + + var c = vX.Key.CompareTo(vY.Key); + + if (_ascending) + { + if (c != 0) + return c; + } + else + { + if (c != 0) + return -c; + } + + return _ascending + ? attribOfX.Version.CompareTo(attribOfY.Version) + : attribOfY.Version.CompareTo(attribOfX.Version); + + } } } diff --git a/src/Migrator/MigrationLoader.cs b/src/Migrator/MigrationLoader.cs index 397ed43c..8d3f9e63 100644 --- a/src/Migrator/MigrationLoader.cs +++ b/src/Migrator/MigrationLoader.cs @@ -46,13 +46,20 @@ public List MigrationsTypes /// /// Returns the last version of the migrations. /// - public long LastVersion + public IEnumerable> LastVersions { - get - { + get + { + var list = new Dictionary(); if (_migrationsTypes.Count == 0) - return 0; - return GetMigrationVersion(_migrationsTypes[_migrationsTypes.Count - 1]); + return list; + foreach (var type in _migrationsTypes) + { + var v = GetMigrationVersion(type); + if (!list.ContainsKey(v.Key) || list[v.Key] < v.Value) + list[v.Key] = v.Value; + } + return list; } } @@ -61,14 +68,14 @@ public long LastVersion /// /// CheckForDuplicatedVersion public void CheckForDuplicatedVersion() - { - List versions = new List(); + { + var versions = new List>(); foreach (Type t in _migrationsTypes) { - long version = GetMigrationVersion(t); + var version = GetMigrationVersion(t); if (versions.Contains(version)) - throw new DuplicatedVersionException(version); + throw new DuplicatedVersionException(version.Value); versions.Add(version); } @@ -102,27 +109,39 @@ public static List GetMigrationTypes(Assembly asm) /// MigrationAttribute. /// /// Migration type. - /// Version number sepcified in the attribute - public static long GetMigrationVersion(Type t) - { - MigrationAttribute attrib = (MigrationAttribute) - Attribute.GetCustomAttribute(t, typeof(MigrationAttribute)); - - return attrib.Version; - } - - public List GetAvailableMigrations() + /// Version number sepcified in the attribute + public static KeyValuePair GetMigrationVersion(Type t) + { + var attrib = (MigrationAttribute) + Attribute.GetCustomAttribute(t, typeof (MigrationAttribute)); + return attrib.GetVersion(t); + } + + public List> GetAvailableMigrations() { //List availableMigrations = new List(); - _migrationsTypes.Sort(new MigrationTypeComparer(true)); - return _migrationsTypes.ConvertAll(new Converter(GetMigrationVersion)); - } - - public IMigration GetMigration(long version) + _migrationsTypes.Sort(new MigrationTypeComparer(true)); + return _migrationsTypes.ConvertAll(GetMigrationVersion); + } + + public List GetAvailableMigrations(string scope) + { + var all = GetAvailableMigrations(); + var list = new List(); + foreach (var keyValuePair in all) + { + if (keyValuePair.Key == scope) + list.Add(keyValuePair.Value); + } + return list; + } + + public IMigration GetMigration(string scope, long version) { - foreach (Type t in _migrationsTypes) - { - if (GetMigrationVersion(t) == version) + foreach (Type t in _migrationsTypes) + { + var v = GetMigrationVersion(t); + if (v.Key == scope && v.Value == version) { IMigration migration = (IMigration)Activator.CreateInstance(t); migration.Database = _provider; diff --git a/src/Migrator/Migrator.cs b/src/Migrator/Migrator.cs index c41c204e..1d86d649 100644 --- a/src/Migrator/Migrator.cs +++ b/src/Migrator/Migrator.cs @@ -79,16 +79,39 @@ public List MigrationsTypes /// /// Run all migrations up to the latest. Make no changes to database if /// dryrun is true. - /// - public void MigrateToLastVersion() - { - MigrateTo(_migrationLoader.LastVersion); + /// + public void MigrateToLastVersion(string scope) + { + foreach (var version in _migrationLoader.LastVersions) + { + if (version.Key != scope) + continue; + MigrateTo(version.Key, version.Value); + break; + } + } + + public IEnumerable Scopes + { + get + { + foreach (var version in _migrationLoader.LastVersions) + yield return version.Key; + } + } + + public void MigrateAllScopesToLastVersion() + { + foreach (var version in _migrationLoader.LastVersions) + { + MigrateTo(version.Key, version.Value); + } } /// /// Returns the current migrations applied to the database. /// - public List AppliedMigrations + public List> AppliedMigrations { get { return _provider.AppliedMigrations; } } @@ -110,20 +133,21 @@ public virtual bool DryRun { get { return _dryrun; } set { _dryrun = value; } - } - - /// - /// Migrate the database to a specific version. - /// Runs all migration between the actual version and the - /// specified version. - /// If version is greater then the current version, - /// the Up() method will be invoked. - /// If version lower then the current version, - /// the Down() method of previous migration will be invoked. - /// If dryrun is set, don't write any changes to the database. - /// - /// The version that must became the current one - public void MigrateTo(long version) + } + + /// + /// Migrate the database to a specific version. + /// Runs all migration between the actual version and the + /// specified version. + /// If version is greater then the current version, + /// the Up() method will be invoked. + /// If version lower then the current version, + /// the Down() method of previous migration will be invoked. + /// If dryrun is set, don't write any changes to the database. + /// + /// Scope of versions + /// The version that must became the current one + public void MigrateTo(string scope, long version) { if (_migrationLoader.MigrationsTypes.Count == 0) @@ -133,13 +157,13 @@ public void MigrateTo(long version) } bool firstRun = true; - BaseMigrate migrate = BaseMigrate.GetInstance(_migrationLoader.GetAvailableMigrations(), _provider, _logger); + BaseMigrate migrate = BaseMigrate.GetInstance(scope, _migrationLoader.GetAvailableMigrations(scope), _provider, _logger); migrate.DryRun = DryRun; Logger.Started(migrate.AppliedVersions, version); while (migrate.Continue(version)) - { - IMigration migration = _migrationLoader.GetMigration(migrate.Current); + { + IMigration migration = _migrationLoader.GetMigration(scope, migrate.Current); if (null == migration) { _logger.Skipping(migrate.Current);