/// <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);
            }
        }
Exemple #2
0
        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);
            }
        }