public DatabaseUpgrade(UpgradeManifest manifest, string connectionString) { if (manifest == null) { throw new ArgumentNullException("manifest"); } if (string.IsNullOrEmpty(connectionString)) { throw new ArgumentOutOfRangeException("connectionString"); } this.manifest = manifest; this.connectionString = connectionString; // Load current version number var currentVersionString = QestlabDatabaseHelper.GetSystemValue(this.connectionString, "QestnetDatabaseVersion"); if (!string.IsNullOrEmpty(currentVersionString)) { if (!Version.TryParse(currentVersionString, out this.currentVersion)) { throw new Exception("The current QestnetDatabaseVersion in qestSystemValues is not a valid version number."); } } this.CheckVersion(); }
public Task ExecuteAsync(CancellationToken cancellationToken) { var task = new Task(() => { this.Message("Commencing database upgrade..."); this.Message(string.Format("Current database version: {0}", this.currentVersion == default(Version) ? "none" : this.currentVersion.ToString())); // Set the repair option unless it is a brand new database in which case option cannot be set if (this.currentVersion != default(Version)) { this.SetOption("Repair", this.OptionRepair ? "True" : "False"); } // Execute the files for (int i = 0; i < this.manifest.ScriptFiles.Length; i++) { this.Message(string.Format("Executing file '{0}' ({1} of {2}) ...", this.manifest.ScriptFiles[i].Name, i + 1, this.manifest.ScriptFiles.Length)); TransactionScope ts = null; try { if (!DisableTransactionScope) { ts = TransactionUtils.CreateTransactionScope(); } using (var conn = new SqlConnection(connectionString)) { conn.InfoMessage += this.PrintInfoMessage; conn.Open(); var script = new UpgradeScript(this.manifest.ScriptFiles[i], conn); script.Message = this.Message; var scriptTask = script.ExecuteAsync(cancellationToken); scriptTask.Start(); scriptTask.Wait(); // wait for script to finish if (cancellationToken.IsCancellationRequested) { if (DisableTransactionScope) { this.Message("Database upgrade cancelled. WARNING: Transactions have been disabled, so this script may have been partially committed!"); } else { this.Message("Database upgrade cancelled. Completed files have been committed."); } return; } } if (ts != null) { ts.Complete(); } } catch (Exception e) { var sb = new StringBuilder(); sb.Append(e.ToString()); this.Message(e.ToString()); var innerException = e.InnerException; while (innerException != null) { if (!sb.ToString().Contains(innerException.ToString())) { this.Message(innerException.ToString()); sb.Append(innerException.ToString()); } innerException = innerException.InnerException; } if (this.DisableTransactionScope) { this.Message(string.Format("File '{0}' aborted due to an unhandled exception. WARNING: Transactions have been disabled, so this script may have been partially committed!", this.manifest.ScriptFiles[i].Name)); } else { this.Message(string.Format("File '{0}' aborted due to an unhandled exception. No changes were committed for this file.", this.manifest.ScriptFiles[i].Name)); } this.SetOption("Repair", "False"); this.Message("Database upgrade aborted."); return; } finally { if (ts != null) { ts.Dispose(); ts = null; } } } this.Message(string.Format("Writing new database version: {0}", this.manifest.UpgradeVersion.ToString())); QestlabDatabaseHelper.SetSystemValue(this.connectionString, systemValueName, this.manifest.UpgradeVersion.ToString()); this.SetOption("Repair", "False"); this.Message("Database upgrade complete."); } ); return(task); }
// fixme: parameterise etc protected void SetOption(string name, string value) { QestlabDatabaseHelper.SetSystemValue(this.connectionString, "QestnetUpgradeOption_" + name, value); this.Message(string.Format("Set upgrade option '{0}' = '{1}',", "QestnetUpgradeOption_" + name, value)); }