/// <summary> /// Run migration for all databases /// </summary> /// <param name="runner"></param> /// <param name="forceApplyScripts">true : force apply scripts even if we have invaild scripts</para> public static void Process(this ExtMigrationRunner runner, bool forceApplyScripts) { if (!forceApplyScripts && runner.HasInvaildScripts) { Logger.Info("There is some invaild scripts, if you want to force apply them, you must config forceApplyScripts = true"); return; } #region Check settings if (string.IsNullOrWhiteSpace(runner.RootNamespace)) { throw new ArgumentNullException(nameof(runner.RootNamespace), "Value should not null or empty"); } if (runner.DatabaseKeys == null) { throw new ArgumentNullException(nameof(runner.DatabaseKeys), "Value should not null"); } #endregion var migrationDatabases = runner.DatabaseKeys.Select(dbKey => new MigrateDatabaseContext(runner.RootNamespace, dbKey.Value)).ToList(); foreach (var dbContext in migrationDatabases) { Process(runner, dbContext, forceApplyScripts); } }
public static ExtMigrationRunner ForRootNamespace(this ExtMigrationRunner runner, string rootNamespace) { if (string.IsNullOrWhiteSpace(rootNamespace)) { throw new ArgumentNullException(nameof(rootNamespace), "<rootNamespace> should not null or empty"); } runner.RootNamespace = rootNamespace; return(runner); }
public static ExtMigrationRunner ForDatabaseLayers(this ExtMigrationRunner runner, SortedList <int, DatabaseScriptType> layers) { if (layers == null) { throw new ArgumentNullException(nameof(layers), "<layers> should not null"); } runner.DatabaseScriptTypes = new SortedList <int, DatabaseScriptType>(); if (layers.Any()) { foreach (var item in layers) { runner.DatabaseScriptTypes.Add(item.Key, item.Value); } } return(runner); }
public static ExtMigrationRunner ForDatabases(this ExtMigrationRunner runner, SortedList <int, string> databaseKeys) { if (databaseKeys == null) { throw new ArgumentNullException(nameof(databaseKeys), "<databaseKeys> should not null"); } runner.DatabaseKeys = new SortedList <int, string>(); if (databaseKeys.Any()) { foreach (var item in databaseKeys) { if (!string.IsNullOrWhiteSpace(item.Value)) { runner.DatabaseKeys.Add(item.Key, item.Value); } } } return(runner); }
/// <summary> /// Run migration for specific database /// </summary> /// <param name="runner"></param> /// <param name="dbContext"></param> public static void Process(this ExtMigrationRunner runner, MigrateDatabaseContext dbContext, bool forceApplyScripts) { if (!forceApplyScripts && runner.HasInvaildScripts) { Logger.Info("There is some invaild scripts, if you want to force apply them, you must config forceApplyScripts = true"); return; } Logger.InfoFormat($"DATEBASE: {dbContext.DatabaseKey} ({dbContext.DatabaseName})"); #region Check settings if (runner.DatabaseScriptTypes == null) { throw new ArgumentNullException(nameof(runner.DatabaseScriptTypes), "Value should not null"); } if (runner.MigrationAssembly == null) { throw new ArgumentNullException(nameof(runner.MigrationAssembly), "Value should not null"); } #endregion try { foreach (var scriptType in runner.DatabaseScriptTypes) { ApplyMigrationUp(dbContext, scriptType.Value, runner.MigrationAssembly); } Logger.InfoFormat($"=> [{dbContext.DatabaseKey}] is done"); Logger.InfoFormat(Environment.NewLine); } catch (Exception ex) { Logger.Error(ex); throw; } }
/// <summary> /// Initialize default settings /// </summary> /// <returns></returns> public static ExtMigrationRunner Initialize() { var runner = new ExtMigrationRunner(); #region Initialize RootNamespace var rootNamespaceFromAppSetting = ConfigurationManager.AppSettings["mgr:RootNamespace"]; if (string.IsNullOrWhiteSpace(rootNamespaceFromAppSetting)) { throw new ArgumentException("<rootNamespace> should not null or empty"); } else { runner.RootNamespace = rootNamespaceFromAppSetting; } #endregion #region Initialize DatabaseKeys if (runner.DatabaseKeys == null) { runner.DatabaseKeys = new SortedList <int, string>(); } var databaseKeys = ConfigurationManager.AppSettings["mgr:DatabaseKeys"]; if (!string.IsNullOrWhiteSpace(databaseKeys)) { var databaseKeyArr = databaseKeys.Split(','); if (databaseKeyArr.Any()) { for (var i = 0; i < databaseKeyArr.Length; i++) { if (!string.IsNullOrWhiteSpace(databaseKeyArr[i])) { runner.DatabaseKeys.Add(i, databaseKeyArr[i].Trim()); } } } } #endregion #region Initialize DatabaseLayers if (runner.DatabaseScriptTypes == null) { runner.DatabaseScriptTypes = new SortedList <int, DatabaseScriptType>(); } var layers = Enum.GetValues(typeof(DatabaseScriptType)) .OfType <DatabaseScriptType>().OrderBy(x => x); foreach (var layer in layers) { runner.DatabaseScriptTypes.Add((int)layer, layer); } #endregion #region Initialize MigrationAssembly var usedAttrAssemblies = AppDomain.CurrentDomain.GetAssemblies() .Where(assy => assy != typeof(ExtMigrationRunner).Assembly) .FirstOrDefault(assy => assy.GetTypes() .Select(type => Attribute.IsDefined(type, typeof(BaseExtMgrAttribute))) .Any(x => x)); if (usedAttrAssemblies != null) { runner.MigrationAssembly = usedAttrAssemblies; } #endregion ShowValidateScripts(runner); return(runner); }
static void ShowValidateScripts(ExtMigrationRunner runner) { runner.HasInvaildScripts = false; // warning invalid scripts var invalidScripts = new List <KeyValuePair <Type, string> >(); var allScriptFiles = runner.MigrationAssembly.GetTypes() .Where(type => type.IsSubclassOf(typeof(MigrationBase))) .ToList(); var validNamespaces = new Dictionary <string, string>(); foreach (var dbKey in runner.DatabaseKeys) { if (!validNamespaces.ContainsKey(dbKey.Value)) { validNamespaces.Add(dbKey.Value, $"{runner.RootNamespace}.{dbKey.Value}"); } } var duplicateVersionsTmp = new List <string>(); foreach (var script in allScriptFiles) { if (!validNamespaces.Values.Contains(script.Namespace)) { invalidScripts.Add(new KeyValuePair <Type, string>(script, "[INCORRECT NAMESPACE]")); continue; } else { var dbKey = validNamespaces.First(x => x.Value == script.Namespace); if (!script.IsPublic) { invalidScripts.Add(new KeyValuePair <Type, string>(script, $"[NOT PUBLIC - {{{dbKey.Key}}}]")); continue; } var migAttr = script.GetCustomAttributes(typeof(BaseExtMgrAttribute), false).FirstOrDefault(); if (migAttr != null) { var versionLong = ((BaseExtMgrAttribute)migAttr).Version; var key = $"{dbKey.Key}.{versionLong}"; if (BaseExtMgrAttribute.VersionBank != null && BaseExtMgrAttribute.VersionBank.ContainsKey(versionLong)) { var dtVersion = BaseExtMgrAttribute.VersionBank[versionLong]; var versionInvailMsg = ValidateMigrateVersion(dtVersion.Year, dtVersion.Month, dtVersion.Day, dtVersion.Hour, dtVersion.Minute, dtVersion.Second); if (!string.IsNullOrWhiteSpace(versionInvailMsg)) { invalidScripts.Add(new KeyValuePair <Type, string>(script, versionInvailMsg)); continue; } } if (duplicateVersionsTmp.Contains(key)) { invalidScripts.Add(new KeyValuePair <Type, string>(script, $"[DUPLICATE VERSION - {{{dbKey.Key}}}]")); continue; } duplicateVersionsTmp.Add(key); ValidScriptsStore.Add($"{versionLong}.{dbKey.Key}"); } else { invalidScripts.Add(new KeyValuePair <Type, string>(script, $"[INCORRECT ATTRIBUTE - {{{dbKey.Key}}}]")); continue; } } } if (invalidScripts.Any()) { runner.HasInvaildScripts = true; Logger.Info($"There are some invalid scripts:"); foreach (var item in invalidScripts.OrderBy(x => x.Key.Name)) { Logger.Info($" > {item.Key.Name} {item.Value}"); } Logger.Info(""); } }
/// <summary> /// Run migration for all databases, stop if it see any invalid migration scripts /// </summary> /// <param name="runner"></param> public static void Process(this ExtMigrationRunner runner) { Process(runner, false); }
public static ExtMigrationRunner ForMigrationAssembly(this ExtMigrationRunner runner, Assembly migrationAssembly) { runner.MigrationAssembly = migrationAssembly ?? throw new ArgumentNullException(nameof(migrationAssembly), "<migrationAssembly> should not null"); return(runner); }