OpenSource » Database Migrator » Migrator2
Clone URL:  
Pushed to one repository · View In Graph Contained in tip

Migrator Case 50595
Work on redesigned migrator

Changeset 756c45455cdb

Parent 405057187903

by Profile picture of Daniel PupekDaniel Pupek

Changes to 9 files · Browse files at 756c45455cdb Showing diff from parent 405057187903 Diff from another changeset...

 
1
 
 
2
3
4
5
6
7
8
9
10
11
12
13
 
 
 
 
 
 
 
 
 
14
15
16
17
18
19
20
 
 
 
 
 
 
21
22
23
 
 
1
2
3
4
5
 
 
 
 
 
 
 
 
 
6
7
8
9
10
11
12
13
14
15
 
 
 
 
 
 
16
17
18
19
20
21
22
23
24
@@ -1,23 +1,24 @@
-Database migrator - v@(Model.Version.Major).@(Model.Version.Minor).@(Model.Version.Revision) +Database Migrator Version - @(Model.Version.Major).@(Model.Version.Minor).@(Model.Version.Revision) +Migrator CLI Utility Version - @(Model.CliVer.Major).@(Model.CliVer.Minor).@(Model.CliVer.Revision)    usage:  Migrator.Console.exe provider connectionString - migrationsAssembly [options] - -provider The database provider - (SqlServer, MySql, Postgre) -connectionString Connection string to the - database -migrationAssembly Path to the assembly - containing the migrations - + migrationsAssembly [options] + +provider The database provider + (SqlServer, MySql, Postgre) +connectionString Connection string to the + database +migrationAssembly Path to the assembly + containing the migrations +  Options: --to=<version> Migrates to specified version --up Migrates up a version --down Migrates down a version --list List migrations --trace Show debug informations --h, -help, -? Prints this message +-to=<version> Migrates to specified version +-up Migrates up a version +-down Migrates down a version +-list List migrations +-trace Show debug informations +-h, -help, -? Prints this message    Reamarks:  -up, -down, and -to options are mutually
 
57
58
59
 
60
61
62
 
57
58
59
60
61
62
63
@@ -57,6 +57,7 @@
  <ItemGroup>   <Compile Include="Boot.cs" />   <Compile Include="MigratorConsole.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" />   </ItemGroup>   <ItemGroup>   <ProjectReference Include="..\core\Migrator.csproj">
 
117
118
119
 
 
 
 
120
121
 
 
122
123
124
125
126
 
 
127
128
129
 
148
149
150
 
 
151
152
153
 
154
155
156
 
157
158
159
 
205
206
207
 
208
209
210
 
213
214
215
216
 
217
218
219
 
117
118
119
120
121
122
123
124
125
126
127
128
129
130
 
 
131
132
133
134
135
 
154
155
156
157
158
159
 
 
160
161
162
 
163
164
165
166
 
212
213
214
215
216
217
218
 
221
222
223
 
224
225
226
227
@@ -117,13 +117,19 @@
    Migrator mig = GetMigrator();   int currentVersion = mig.LatestVersion; + bool isLegacy = mig.IsLegacyAssembly(); + + if(isLegacy) + Console.WriteLine("This database is a v1.0 migrated database. If it is migrated again then it will be converted to 2.0.");     Console.WriteLine("Available migrations:"); + Console.WriteLine("[C] = Current, [R] = Already Run, [N] = Not run, [L] = Legacy Migrator"); +   foreach (Type t in mig.MigrationsTypes)   {   int v = Migrator.GetMigrationVersion(t); - Console.WriteLine("{0} {1} {2}", - v == currentVersion ? "=>" : " ", + Console.WriteLine("[{0}] {1} {2} ", + v == currentVersion ? "C" : isLegacy ? v < currentVersion ? "R" : "N" : mig.HasMigrationRun(v) ? "R" : "N",   v.ToString().PadLeft(3),   Migrator.GetMigrationDescription(t)   ); @@ -148,12 +154,13 @@
  public void PrintUsage()   {   int tab = 17; + var migratorAssembly = Assembly.GetAssembly(typeof(Migrator)); + Version ver = migratorAssembly.GetName().Version;   var executingAssembly = Assembly.GetExecutingAssembly(); - Version ver = executingAssembly.GetName().Version; - + var cliVer = executingAssembly.GetName().Version;     var text = new StreamReader(executingAssembly.GetManifestResourceStream("Migrator.Console.HelpText.txt")).ReadToEnd(); - Console.Write(Razor.Parse(text, new {Version=ver}, "helpText")); + Console.Write(Razor.Parse(text, new { Version = ver, CliVer = cliVer }, "helpText"));     }   @@ -205,6 +212,7 @@
  if (_provider == null) messages.Add("Provider not specified (SqlServer, MySql, Postgre).");   if (_connectionString == null) messages.Add("Connection string not specified.");   if (_migrationsAssembly == null) messages.Add("Migration assembly not specified"); + if (!File.Exists(_migrationsAssembly)) messages.Add("Migration assembly not not found at " + _migrationsAssembly);   if (messages.Count > 0)   throw new ArgumentException("\n\n" + String.Join(" \n", messages.ToArray()) + "\n\n");   } @@ -213,7 +221,7 @@
  private Migrator GetMigrator()   {   Assembly migAssem = GetAssembly(); - GuidAttribute guidAttribute = (GuidAttribute)Attribute.GetCustomAttribute(migAssem, typeof(GuidAttribute)); +   // This is done incase we are scanning a 4.0 dll, the console is compiled against 4.0 so it can do all the assembly scanning   var logger = new Loggers.ConsoleLogger(_trace);   return new Migrator(_provider, _connectionString, migAssem, logger);
Change 1 of 1 Show Entire File app/​console/​Properties/​AssemblyInfo.cs Stacked
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@@ -0,0 +1,35 @@
+using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Resources; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Database Migration CLI Tool")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Darwin Global, LLC")] +[assembly: AssemblyProduct("Database Migration CLI Tool")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("bbda83ad-1b97-4abf-a7eb-6b6caad66e5e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")] +[assembly: NeutralResourcesLanguageAttribute("en-US")]
 
5
6
7
8
 
9
10
11
12
13
 
 
 
14
15
16
 
29
30
31
32
33
 
 
34
 
 
5
6
7
 
8
9
10
 
 
 
11
12
13
14
15
16
 
29
30
31
 
 
32
33
34
35
@@ -5,12 +5,12 @@
 // General Information about an assembly is controlled through the following  // set of attributes. Change these attribute values to modify the information  // associated with an assembly. -[assembly: AssemblyTitle("Migrator")] +[assembly: AssemblyTitle("Database Migrator Utility")]  [assembly: AssemblyDescription("")]  [assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Microsoft")] -[assembly: AssemblyProduct("Migrator")] -[assembly: AssemblyCopyright("Copyright © Microsoft 2011")] +[assembly: AssemblyCompany("Darwin Global, LLC")] +[assembly: AssemblyProduct("Database Migrator")] +[assembly: AssemblyCopyright("Copyright © Darwin Global, LLC")]  [assembly: AssemblyTrademark("")]  [assembly: AssemblyCulture("")]   @@ -29,6 +29,7 @@
 // Build Number  // Revision  // -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("2.0.0.0")] +[assembly: AssemblyFileVersion("2.0.0.0")]  [assembly: InternalsVisibleTo("Migrator.Tests")] +[assembly: InternalsVisibleTo("Migrator.Console")]
 
54
55
56
 
57
58
59
 
61
62
63
 
64
65
66
 
54
55
56
57
58
59
60
 
62
63
64
65
66
67
68
@@ -54,6 +54,7 @@
  public void Exception(int version, string migrationName, Exception ex)   {   Console.WriteLine("{0} Error in migration {1} : {2}", "".PadLeft(_widthFirstColumn), version, ex.Message); + Console.WriteLine("{0} Stack: \n {1}", "".PadLeft(_widthFirstColumn),ex.StackTrace);   this.TraceException(ex);   }   @@ -61,6 +62,7 @@
  {   Console.Write("{0} ", "".PadLeft(_widthFirstColumn));   Console.WriteLine(format, args); + Console.WriteLine("{0} Stack: \n {1}", "".PadLeft(_widthFirstColumn), ex.StackTrace);   this.TraceException(ex);   }  
 
61
62
63
64
 
65
66
67
 
61
62
63
 
64
65
66
67
@@ -61,7 +61,7 @@
    {typeof(float),size=>{return size == 0 ? "real" : string.Format("float({0})", size);}},   {typeof(double),size=>{return size == 0 ? "real" : string.Format("float({0})", size);}}, - {typeof(decimal),size=>{return size == 0 ? "real" : string.Format("float({0})", size);}}, + {typeof(decimal),size=> "decimal"},     {typeof(bool),size=>{return "bit";}},   {typeof(DateTime),size=>{return "datetime";}},
 
20
21
22
 
23
24
25
 
32
33
34
35
36
 
37
38
39
 
111
112
113
 
114
115
116
 
141
142
143
144
 
145
146
147
 
149
150
151
152
153
 
154
155
156
 
164
165
166
167
168
169
170
171
172
173
 
 
 
 
 
174
175
176
 
220
221
222
223
224
225
226
227
228
229
 
 
 
 
230
231
 
232
233
234
 
288
289
290
291
 
292
293
294
 
372
373
374
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376
377
 
387
388
389
390
391
 
392
393
394
 
415
416
417
 
418
419
420
421
422
423
424
 
425
426
427
428
429
430
431
432
433
 
434
435
436
 
447
448
449
 
 
 
 
 
 
 
 
450
451
 
 
 
 
 
 
 
452
453
454
455
456
457
458
459
 
 
 
 
460
461
462
 
478
479
480
481
 
 
482
483
484
 
 
 
 
485
486
487
488
 
 
 
 
 
 
 
 
 
 
 
489
490
491
 
657
658
659
660
 
661
662
663
 
667
668
669
670
 
671
672
673
 
700
701
702
703
 
704
705
706
 
710
711
712
 
 
 
 
 
 
 
 
 
 
713
714
 
20
21
22
23
24
25
26
 
33
34
35
 
 
36
37
38
39
 
111
112
113
114
115
116
117
 
142
143
144
 
145
146
147
148
 
150
151
152
 
 
153
154
155
156
 
164
165
166
 
 
 
 
 
 
167
168
169
170
171
172
173
174
175
 
219
220
221
 
 
 
 
 
 
 
222
223
224
225
226
 
227
228
229
230
 
284
285
286
 
287
288
289
290
 
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
 
399
400
401
 
 
402
403
404
405
 
426
427
428
429
430
431
432
433
434
435
 
436
437
438
439
440
441
442
 
443
 
444
445
446
447
 
458
459
460
461
462
463
464
465
466
467
468
469
 
470
471
472
473
474
475
476
477
 
 
 
 
 
 
 
478
479
480
481
482
483
484
 
500
501
502
 
503
504
505
 
 
506
507
508
509
510
 
 
 
511
512
513
514
515
516
517
518
519
520
521
522
523
524
 
690
691
692
 
693
694
695
696
 
700
701
702
 
703
704
705
706
 
733
734
735
 
736
737
738
739
 
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
@@ -20,6 +20,7 @@
 using System.Text.RegularExpressions;  using System.Collections.Generic;  using System.Linq; +using Mono.Security.X509;    #endregion   @@ -32,8 +33,7 @@
  {   #region Fields   private TransformationProvider _provider; - private List<Type> _migrationsTypes = new List<Type>(); - private ILogger _logger = new NullLogger(); + private ILogger _logger = new NullLogger();   private log4net.ILog _log4netlogger = log4net.LogManager.GetLogger("Migrator");   private Dictionary<string, string> _parameters;   private Dictionary<string, TransformationProvider> _additionalProviders = new Dictionary<string, TransformationProvider>(); @@ -111,6 +111,7 @@
  /// <param name="logger"></param>   public Migrator(TransformationProvider provider, Assembly migrationAssembly, ILogger logger)   { + MigrationsTypes = new List<Type>();   _provider = provider;   _logger = logger;   _provider.Logger = _logger; @@ -141,7 +142,7 @@
    // only load the migrations for the given assembly   - _migrationsTypes = GetMigrationTypes(migrationAssembly).ToList(); + MigrationsTypes = GetMigrationTypes(migrationAssembly).ToList();     this.BeginMigration = GetBeginMigration(migrationAssembly);   this.EndMigration = GetEndMigration(migrationAssembly); @@ -149,8 +150,7 @@
  CheckForDuplicatedVersion();   }   - - +   /// <summary>   /// Extracts settings from the assembly   /// </summary> @@ -164,13 +164,12 @@
    if(!string.IsNullOrEmpty(settings.SchemaInfoTableName)) _provider.SetSchemaInfoTable(settings.SchemaInfoTableName);   - var guid = migratingAssembly.GetCustomAttributes(typeof(GuidAttribute), false).Cast<GuidAttribute>().ToList(); - if (guid.Count > 0) - { - _provider.AssemblyId = guid[0].Value; - } -   } + var guid = migratingAssembly.GetCustomAttributes(typeof(GuidAttribute), false).Cast<GuidAttribute>().ToList(); + if (guid.Count > 0) + { + _provider.AssemblyId = guid[0].Value; + }   }   #endregion   @@ -220,15 +219,12 @@
    }   - /// <summary> - /// Returns registered migration <see cref="System.Type">types</see>. - /// </summary> - public List<Type> MigrationsTypes - { - get { return _migrationsTypes; } - } + /// <summary> + /// Returns registered migration <see cref="System.Type">types</see>. + /// </summary> + public List<Type> MigrationsTypes { get; private set; }   - /// <summary> + /// <summary>   /// Get or set the event logger.   /// </summary>   public ILogger Logger @@ -288,7 +284,7 @@
  MigrationAttribute attrib = (MigrationAttribute)   Attribute.GetCustomAttribute(t, typeof(MigrationAttribute));   - return attrib.Description == null ? t.Name : attrib.Description; + return attrib.Description ?? t.Name;   }     /// <summary> @@ -372,6 +368,22 @@
  #endregion     #region Migration Methods + + /// <summary> + /// + /// </summary> + /// <returns></returns> + public bool IsLegacyAssembly() + { + if (!_provider.TableExists(_provider.OldSchemaInfoTable)) + return false; + + using (var reader = _provider.ExecuteQuery("Select Top 1 AssemblyId From {0} WHERE AssemblyId = '{1}'", + _provider.OldSchemaInfoTable, _provider.AssemblyId)) + { + return (reader.Read()); + } + }   /// <summary>   /// Migrate the database to a specific version.   /// Runs all migration between the actual version and the @@ -387,8 +399,7 @@
  GetReady();     int originalVersion = this.LatestVersion; - int executingMigrationVersion = this.LatestVersion; - +   // check for cases where migration is unnecessary or impossible   if (toVersion == this.LatestVersion)   { @@ -415,22 +426,22 @@
    this._logger.Started(LatestVersion, toVersion);   IEnumerable<int> migratedVersions = new List<int>(); + _provider.CreateMigrationTrackingTable();     if (goingUp)   migratedVersions = InternalMigrateUpTo(toVersion);   else   migratedVersions = InternalMigrateDownTo(toVersion);   - _provider.CreateMigrationTrackingTable(); +   this.CommitTransactions();     this._logger.Finished(originalVersion, this.LatestVersion);   }   catch (Exception exception)   { - this._logger.Exception(executingMigrationVersion, GetMigrationDescription(GetMigration(executingMigrationVersion).GetType()), exception);   this._logger.RollingBack(originalVersion); - _log4netlogger.Fatal("Migration to version " + executingMigrationVersion + " failed going from version " + originalVersion + " to " + toVersion, exception); +   this.RollbackTransactions();   throw;   } @@ -447,16 +458,27 @@
  Queue<Migration> migrations = GetMigrationsToBeRunDown(toVersion);     var migratedVersions = new List<int>(); + int migratingVersion = -1; + try + { + + while (migrations.Count > 0) + { + var currentMigration = migrations.Dequeue(); + migratingVersion = GetMigrationVersion(currentMigration.GetType());   - while (migrations.Count > 0) + this._logger.MigrateDown(migratingVersion, GetMigrationDescription(currentMigration.GetType())); + currentMigration.Down(); + + migratedVersions.Add(migratingVersion); + } + } + catch (Exception e)   { - var currentMigration = migrations.Dequeue(); - var version = GetMigrationVersion(currentMigration.GetType()); - - this._logger.MigrateDown(version, GetMigrationDescription(currentMigration.GetType())); - currentMigration.Down(); - - migratedVersions.Add(version); + if (migratingVersion < 1) + this._logger.Exception("Failed to begin migrating.", e); + else + this._logger.Exception(migratingVersion, GetMigrationDescription(GetMigration(migratingVersion).GetType()), e);   }     InitializeMigration(BeginMigration).Down(); @@ -478,14 +500,25 @@
  Queue<Migration> migrations = GetMigrationsToBeRunUP(toVersion);   var migratedVersions = new List<int>();   - while (migrations.Count > 0) + int migratingVersion = -1; + try   { - var currentMigration = migrations.Dequeue(); - var version = GetMigrationVersion(currentMigration.GetType()); + while (migrations.Count > 0) + { + var currentMigration = migrations.Dequeue(); + migratingVersion = GetMigrationVersion(currentMigration.GetType());   - this._logger.MigrateUp(version, GetMigrationDescription(currentMigration.GetType())); - currentMigration.Up(); - migratedVersions.Add(version); + this._logger.MigrateUp(migratingVersion, GetMigrationDescription(currentMigration.GetType())); + currentMigration.Up(); + migratedVersions.Add(migratingVersion); + } + } + catch (Exception e) + { + if(migratingVersion < 1) + this._logger.Exception("Failed to begin migrating.", e); + else + this._logger.Exception(migratingVersion, GetMigrationDescription(GetMigration(migratingVersion).GetType()), e);   }     InitializeMigration(EndMigration).Up(); @@ -657,7 +690,7 @@
    // Print a list of loaded Migrations   _logger.Trace("Loaded migrations:"); - foreach (Type t in _migrationsTypes) + foreach (Type t in MigrationsTypes)   {   _logger.Trace("{0} {1}", GetMigrationVersion(t).ToString().PadLeft(5), GetMigrationDescription(t));   } @@ -667,7 +700,7 @@
  private Type GetMigrationType(int version)   {   // since the list is sorted and contiguous getting an item is simple: - return _migrationsTypes.FirstOrDefault(m => GetMigrationVersion(m) == version); + return MigrationsTypes.FirstOrDefault(m => GetMigrationVersion(m) == version);   }     private Migration GetMigration(int version) @@ -700,7 +733,7 @@
  {   var versions = new List<int>();   - foreach (Type t in _migrationsTypes) + foreach (Type t in MigrationsTypes)   {   int version = GetMigrationVersion(t);   if (versions.Contains(version)) @@ -710,5 +743,15 @@
  }   }   #endregion + + /// <summary> + /// Returns true if the version migration has been run already + /// </summary> + /// <param name="version"></param> + /// <returns></returns> + public bool HasMigrationRun(int version) + { + return _provider.HasMigrationRun(version); + }   }  }
 
39
40
41
42
 
43
44
45
 
563
564
565
566
 
567
568
569
 
647
648
649
650
651
 
 
 
 
 
 
652
653
654
 
737
738
739
740
741
742
743
 
 
 
 
 
 
744
745
746
 
39
40
41
 
42
43
44
45
 
563
564
565
 
566
567
568
569
 
647
648
649
 
 
650
651
652
653
654
655
656
657
658
 
741
742
743
 
 
 
 
744
745
746
747
748
749
750
751
752
@@ -39,7 +39,7 @@
  {   [Obsolete("Stop Using", true)]   protected string SchemaInfoTable = "SchemaInfo"; - protected string OldSchemaInfoTable = "SchemaInfo"; + internal string OldSchemaInfoTable = "SchemaInfo";   protected const string MigrationsTrackingTable = "MigrationTrackingInfo";   protected const string VersionColumn = "Version";   protected const string AssemblyIdColumn = "AssemblyId"; @@ -563,7 +563,7 @@
    oldVersion = (int?)ExecuteScalar(String.Format("SELECT Version FROM {1} WHERE AssemblyId='{0}'", AssemblyId, OldSchemaInfoTable)) ?? 0;   // We have what we needed - ExecuteNonQuery("DELETE from {0} WHERE AssemblyId = {1}", OldSchemaInfoTable, AssemblyId); + ExecuteNonQuery("DELETE from {0} WHERE AssemblyId = '{1}'", OldSchemaInfoTable, AssemblyId);     }   @@ -647,8 +647,12 @@
  /// <returns></returns>   public bool HasMigrationRun(int version)   { - var reader = ExecuteQuery("Select Top 1 Version From {0} WHERE Version = {1} AND AssemblyId = '{2}'", MigrationsTrackingTable, version, AssemblyId); - return reader.Read(); + using ( + var reader = ExecuteQuery("Select Top 1 Version From {0} WHERE Version = {1} AND AssemblyId = '{2}'", + MigrationsTrackingTable, version, AssemblyId)) + { + return reader.Read(); + }   }     #endregion @@ -737,10 +741,12 @@
  /// <returns>A data iterator, <see cref="System.Data.IDataReader">IDataReader</see>.</returns>   internal virtual T ExecuteQuery<T>(string sql)   { - var reader = ExecuteQuery(sql); - if (reader.Read()) - return (T)reader.GetValue(0); - return default(T); + using (var reader = ExecuteQuery(sql)) + { + if (reader.Read()) + return (T) reader.GetValue(0); + return default(T); + }   }     public virtual object ExecuteScalar(string sql)