/// <summary> /// Backup implementation logic, asks SQLServer to make a backup, of <see cref="dbName"/>, creates a Zip archive on success, tries to delete the original backup file. /// </summary> /// <param name="coString">Connection string to use to instruct SQLServer to make the backup</param> /// <param name="dbName">Name of the database to backup</param> /// <param name="principal"></param> /// <param name="logger">Optional instance of a <see cref="Logger"/></param> /// <returns>An instance of <see cref="BackupHistory"/> on success, null otherwise</returns> /// <remarks>If deletion of the original backup file fails for any reason, only a log entry will be done, the backup won't be considered as failed. /// This methods needs to be run in a valid <see cref="HttpContext"/>. /// </remarks> public static async Task <BackupHistory> BackupDatabase([NotNull] string coString, [NotNull] string dbName, [CanBeNull] Logger logger) { if (string.IsNullOrWhiteSpace(coString)) { throw new ArgumentNullException("coString"); } if (string.IsNullOrWhiteSpace(dbName)) { throw new ArgumentNullException("dbName"); } var httpContext = HttpContext.Current; if (httpContext == null) { throw new Exception("HttpContext.Current returned null"); } var server = httpContext.Server; var user = httpContext.User; using (var bak = new SqlServerBackupProvider(coString)) { await bak.OpenAsync(); var ts = DateTime.Now; var backupsPath = server.MapPath("~/Backups"); var fNameBase = Utils.GenerateBackupBaseName(dbName, ts); var fullBackupPath = Path.Combine(backupsPath, string.Format("{0}.bak", fNameBase)); try { await bak.BackupDatabaseAsync(dbName, fullBackupPath, ts); } catch (Exception ex) { if (logger != null) { logger.ErrorException("During database backup", ex); } return(null); } var fullZipPath = Path.Combine(backupsPath, string.Format("{0}.zip", fNameBase)); try { using (var z = new ZipFile(fullZipPath)) { z.AddFile(fullBackupPath, string.Empty); await Task.Run(() => z.Save()); } } catch (Exception ex) { if (logger != null) { logger.ErrorException("During zip file creation", ex); } return(null); } try { File.Delete(fullBackupPath); } catch (Exception ex) { if (logger != null) { logger.ErrorException("During original file deletion", ex); } } var fInfo = new FileInfo(fullZipPath); var h = new BackupHistory { Path = fullZipPath, Database = dbName, Url = string.Format("~/{0}", fullZipPath.Replace(server.MapPath("~/"), string.Empty).Replace('\\', '/')), Expires = DateTime.Now.AddDays(1), Username = user.Identity.Name, Size = fInfo.Length, }; using (var ddb = new SSBTDbContext()) { ddb.History.Add(h); ddb.SaveChanges(); } return(h); } }
private static void Main(string[] args) { var showHelp = false; var opts = new OptionSet { { "h|?|help", "Displays this help message", _ => showHelp = _ != null }, { "s|silent", "Put ssbt in silent mode, nothing will be written in the standard output (excludes --readline)", _ => Silent = _ != null }, { "R|readline", "Don't exit directly after finish, wait for a key to be typed", _ => ReadLine = _ != null }, { "d|databases=", "Comma separated list of databases names to backup, overrides App.config databases list", delegate(string _) { if (!string.IsNullOrWhiteSpace(_)) { DatabaseList.AddRange(_.Split(',')); } } }, }; opts.Parse(args); Intro(); if (showHelp) { Console.WriteLine(); Console.WriteLine(" Usage :"); opts.WriteOptionDescriptions(Console.Out); Exit(true); return; } var s = Settings.Default; SqlServerBackupProvider bk; try { bk = new SqlServerBackupProvider(s.BackupConnection); } catch (Exception ex) { Log(1, OutputStatusType.Error, "Something went wrong during SQL connection creation, you should check your connection string."); LogException(ex); Exit(false); return; } using (bk) { try { Log(2, OutputStatusType.Info, "Opening connection..."); bk.Open(); Log(4, OutputStatusType.OK, "Database connection opened"); } catch (Exception ex) { LogException(ex); Log(4, OutputStatusType.Error, "Error while opening database connection !"); Exit(false); return; } // Nothing populated from command line if (DatabaseList.Count == 0) { foreach (var confd in s.DatabaseList) { DatabaseList.Add(confd); } } foreach (var ddb in DatabaseList) { Log(4, OutputStatusType.Info, string.Format("Doing database backup of '{0}'", ddb)); var ts = DateTime.Now; var fNameBase = Utils.GenerateBackupBaseName(ddb, ts); var backupFullPath = Path.Combine( s.BackupPath, string.Format("{0}.bak", fNameBase) ); Log(4, OutputStatusType.Info, string.Format("Output file path : '{0}'", backupFullPath)); try { Log(7, OutputStatusType.Info, "Staring backup..."); bk.BackupDatabase(ddb, backupFullPath, ts); Log(9, OutputStatusType.OK, "Backup done."); } catch (Exception ex) { LogException(ex); Log(9, OutputStatusType.Error, "Error while doing backup"); continue; } if (!File.Exists(backupFullPath)) { Log(7, OutputStatusType.Warning, "Unable to read the backup file, maybe the backup has been done on a remote server ?"); continue; } var toUpload = backupFullPath; if (s.EnableBackupZip) { try { Log(7, OutputStatusType.Info, "Doing backup zip..."); using (var z = new ZipFile()) { var zipFilePath = Path.Combine(s.BackupPath, string.Format("{0}.zip", fNameBase)); z.AddFile(backupFullPath, string.Empty); z.Save(zipFilePath); } Log(9, OutputStatusType.OK, "Zip archive successfully created"); } catch (Exception ex) { LogException(ex); Log(9, OutputStatusType.Error, "Error during zip archive creation"); continue; } if (s.EnableDeleteBackupAfterZip) { try { Log(7, OutputStatusType.Info, "Deleting original backup file..."); File.Delete(backupFullPath); Log(9, OutputStatusType.OK, "Original backup file deleted."); } catch (Exception ex) { LogException(ex); Log(9, OutputStatusType.Error, "Unable to delete original backup file."); } } } } Log(2, OutputStatusType.Info, "All work is done, exiting."); Exit(true); } }