예제 #1
0
        /// <summary>
        ///   Restores each of the backups. If the default file location is available it will move the files to there.
        /// </summary>
        /// <param name="backupOrder">An ordered list of backups to apply.</param>
        /// <param name="databaseName">Database to restore to.</param>
        /// <param name="retryDurationProvider">
        ///   Retry duration function. Retry 10 times, input retry number, output timespan to
        ///   wait
        /// </param>
        /// <param name="fileRelocation">Option for renaming files during the restore.</param>
        public void Restore(IEnumerable <BackupMetadata> backupOrder, string databaseName,
                            Func <int, TimeSpan> retryDurationProvider,
                            Func <string, string> fileRelocation = null)
        {
            var policy = Policy
                         .Handle <ExecutionFailureException>(e => e.InnerException != null &&
                                                             e.InnerException is SqlException &&
                                                             e.InnerException.Message
                                                             .Contains("The process cannot access the file because it is being used by another process"))
                         .WaitAndRetry(10, retryDurationProvider);


            var restore = new Restore {
                Database = databaseName, NoRecovery = true
            };

            foreach (var backup in backupOrder)
            {
                var device           = BackupFileTools.IsValidFileUrl(backup.PhysicalDeviceName) ? DeviceType.Url : DeviceType.File;
                var backupDeviceItem = new BackupDeviceItem(backup.PhysicalDeviceName, device);
                if (_credentialName != null && device == DeviceType.Url)
                {
                    backupDeviceItem.CredentialName = _credentialName;
                }

                restore.Devices.Add(backupDeviceItem);

                var defaultFileLocations = DefaultFileLocations();
                if (defaultFileLocations != null)
                {
                    restore.RelocateFiles.Clear();
                    var fileList = policy.Execute(() => restore.ReadFileList(_server).AsEnumerable());
                    foreach (var file in fileList)
                    {
                        var physicalName = (string)file["PhysicalName"];
                        var fileName     = GetFileName(physicalName);

                        if (fileRelocation != null)
                        {
                            fileName = fileRelocation(fileName);
                        }

                        var path = (string)file["Type"] == "L" ? defaultFileLocations?.Log : defaultFileLocations?.Data;
                        path ??= Path.GetFullPath(physicalName);

                        var newFilePath = Path.Combine(path, fileName);

                        restore.RelocateFiles.Add(new RelocateFile((string)file["LogicalName"], newFilePath));
                    }
                }

                _server.ConnectionContext.StatementTimeout = 86400; // 60 * 60 * 24 = 24 hours

                policy.Execute(() => restore.SqlRestore(_server));
                restore.Devices.Remove(backupDeviceItem);
            }
        }
예제 #2
0
        /// <summary>
        ///   Restores each of the backups. If the default file location is available it will move the files to there.
        /// </summary>
        /// <param name="backupOrder">An ordered list of backups to apply.</param>
        /// <param name="databaseName">Database to restore to.</param>
        /// <param name="fileRelocation">Option for renaming files during the restore.</param>
        public void Restore(IEnumerable <BackupMetadata> backupOrder, string databaseName,
                            Func <string, string> fileRelocation = null)
        {
            var restore = new Restore {
                Database = databaseName, NoRecovery = true
            };

            foreach (var backup in backupOrder)
            {
                var device           = BackupFileTools.IsUrl(backup.PhysicalDeviceName) ? DeviceType.Url : DeviceType.File;
                var backupDeviceItem = new BackupDeviceItem(backup.PhysicalDeviceName, device);
                if (_credentialName != null && device == DeviceType.Url)
                {
                    backupDeviceItem.CredentialName = _credentialName;
                }

                restore.Devices.Add(backupDeviceItem);

                var defaultFileLocations = DefaultFileLocations();
                if (defaultFileLocations != null)
                {
                    restore.RelocateFiles.Clear();
                    foreach (var file in restore.ReadFileList(_server).AsEnumerable())
                    {
                        var physicalName = (string)file["PhysicalName"];
                        var fileName     = Path.GetFileName(physicalName) ??
                                           throw new InvalidBackupException($"Physical name in backup is incomplete: {physicalName}");

                        if (fileRelocation != null)
                        {
                            fileName = fileRelocation(fileName);
                        }

                        var path = (string)file["Type"] == "L" ? defaultFileLocations?.Log : defaultFileLocations?.Data;
                        path = path ?? Path.GetFullPath(physicalName);

                        var newFilePath = Path.Combine(path, fileName);

                        restore.RelocateFiles.Add(new RelocateFile((string)file["LogicalName"], newFilePath));
                    }
                }

                _server.ConnectionContext.StatementTimeout = 86400; // 60 * 60 * 24 = 24 hours

                restore.SqlRestore(_server);
                restore.Devices.Remove(backupDeviceItem);
            }
        }
예제 #3
0
        private void Backup(Backup backup, string backupDirectoryPathQuery, string databaseName,
                            BackupFileTools.BackupType type)
        {
            var backupDirectory = BackupDirectoryOrDefault(backupDirectoryPathQuery);
            var filePath        =
                $"{backupDirectory}/{databaseName}_backup_{DateTime.Now.ToString("yyyy_MM_dd_hhmmss_fff")}.{BackupFileTools.BackupTypeToExtension(type)}";
            var deviceType = BackupFileTools.IsUrl(filePath) ? DeviceType.Url : DeviceType.File;

            var bdi = new BackupDeviceItem(filePath, deviceType);

            if (_credentialName != null && deviceType == DeviceType.Url)
            {
                bdi.CredentialName = _credentialName;
            }

            backup.Devices.Add(bdi);
            backup.SqlBackup(_server);
        }
예제 #4
0
        /// <summary>
        ///   Queries msdb on the instance for backups of this database.
        /// </summary>
        /// <returns>A list of backups known by msdb</returns>
        public List <BackupMetadata> RecentBackups()
        {
            var backups = new List <BackupMetadata>();

            var query = "SELECT s.database_name, m.physical_device_name, s.backup_start_date, s.first_lsn, s.last_lsn," +
                        "s.database_backup_lsn, s.checkpoint_lsn, s.[type] AS backup_type, s.server_name, s.recovery_model " +
                        "FROM msdb.dbo.backupset s " +
                        "INNER JOIN msdb.dbo.backupmediafamily m ON s.media_set_id = m.media_set_id " +
                        "WHERE s.last_lsn >= (" +
                        "SELECT MAX(last_lsn) FROM msdb.dbo.backupset " +
                        "WHERE [type] = 'D' " +
                        "AND database_name = @dbName " +
                        "AND is_copy_only = 0" +
                        ") " +
                        "AND s.database_name = @dbName " +
                        "AND is_copy_only = 0" +
                        "ORDER BY s.backup_start_date DESC, backup_finish_date";

            using var cmd   = _server.SqlConnection.CreateCommand();
            cmd.CommandText = query;
            var dbName = cmd.CreateParameter();

            dbName.ParameterName = "dbName";
            dbName.Value         = _database.Name;
            cmd.Parameters.Add(dbName);

            using var reader = cmd.ExecuteReader();
            while (reader.Read())
            {
                backups.Add(new BackupMetadata {
                    CheckpointLsn      = (decimal)reader["checkpoint_lsn"],
                    DatabaseBackupLsn  = (decimal)reader["database_backup_lsn"],
                    DatabaseName       = (string)reader["database_name"],
                    FirstLsn           = (decimal)reader["first_lsn"],
                    LastLsn            = (decimal)reader["last_lsn"],
                    PhysicalDeviceName = (string)reader["physical_device_name"],
                    ServerName         = (string)reader["server_name"],
                    StartTime          = (DateTime)reader["backup_start_date"],
                    BackupType         = BackupFileTools.BackupTypeAbbrevToType((string)reader["backup_type"])
                });
            }

            return(backups);
        }