Ejemplo n.º 1
0
        // if database name is not provided, dbname from the backup is used.
        // if newStoragePath is not provided, system defaults are used
        internal static void RestoreSqlBackup(ICakeContext context, String connectionString, FilePath backupFile, RestoreSqlBackupSettings settings)
        {
            using (var connection = SqlServerAliasesImpl.OpenSqlConnection(context, connectionString))
            {
                var oldDbName       = GetDatabaseName(backupFile, connection);
                var newDatabaseName = settings.NewDatabaseName ?? oldDbName;
                context.Log.Information($"Using database name '{newDatabaseName}' to be a name for the restored database");

                var logicalNames = GetLogicalNames(backupFile, connection);

                var sql = "";

                if (settings.SwitchToSingleUserMode)
                {
                    sql += $@"
if db_id({Sql.EscapeNameQuotes(newDatabaseName)}) is not null 
begin
    use master;
    alter database {Sql.EscapeName(newDatabaseName)} set single_user with rollback immediate;
end
";
                }

                sql += $"Restore database {Sql.EscapeName(newDatabaseName)} from disk = @backupFile with ";

                for (var i = 0; i < logicalNames.Count; i++)
                {
                    sql += $" move @LName{i} to @LPath{i}";
                    if (i < logicalNames.Count - 1)
                    {
                        sql += ", \r\n"; // only need comma before penultimate list
                    }
                }
                if (settings.WithReplace)
                {
                    sql += ",\r\n replace ";
                }

                sql += $";\r\n alter database {Sql.EscapeName(newDatabaseName)} set multi_user;";

                context.Log.Debug($"Executing SQL : {sql}");

                var pathSeparator = GetPlatformPathSeparator(connection);

                var command = SqlServerAliasesImpl.CreateSqlCommand(sql, connection);
                command.Parameters.AddWithValue("@backupFile", backupFile.ToString());
                for (var i = 0; i < logicalNames.Count; i++)
                {
                    var lParameterName = "@LName" + i;
                    context.Log.Debug($"Adding parameter '{lParameterName}' with value '{logicalNames[i].LogicalName}'");
                    command.Parameters.AddWithValue(lParameterName, logicalNames[i].LogicalName);

                    var filePath      = GetFilePath(connection, oldDbName, newDatabaseName, settings.NewStorageFolder, logicalNames[i], pathSeparator);
                    var pathParamName = "@LPath" + i;
                    context.Log.Debug($"Adding parameter '{pathParamName}' with value '{filePath}'");
                    command.Parameters.AddWithValue(pathParamName, filePath);
                }
                command.ExecuteNonQuery();
            }
        }
Ejemplo n.º 2
0
        internal static List <LogicalNames> GetLogicalNames(FilePath backupFile, SqlConnection connection)
        {
            var fileListSql = @"RESTORE FILELISTONLY from Disk = @backupFile";
            var command     = SqlServerAliasesImpl.CreateSqlCommand(fileListSql, connection);

            command.Parameters.AddWithValue("@backupFile", backupFile.ToString());
            var logicalNames = new List <LogicalNames>();

            using (var reader = command.ExecuteReader())
            {
                if (!reader.HasRows)
                {
                    throw new Exception($"Unable to read logical names from the backup at {backupFile}. Are you sure it is SQL backup file?");
                }
                while (reader.Read())
                {
                    var name = new LogicalNames()
                    {
                        LogicalName  = reader.GetString(reader.GetOrdinal("LogicalName")),
                        PhysicalName = reader.GetString(reader.GetOrdinal("PhysicalName")),
                        Type         = reader.GetString(reader.GetOrdinal("Type")),
                    };

                    logicalNames.Add(name);
                }
            }
            return(logicalNames);
        }
        internal static void Execute(ICakeContext context, string connectionString, string databaseName, BackupDatabaseSettings settings)
        {
            Guard.ArgumentIsNotNull(context, nameof(context));
            Guard.ArgumentIsNotNull(connectionString, nameof(connectionString));
            Guard.ArgumentIsNotNull(settings, nameof(settings));

            var backupFile = GetBackupFileName(databaseName, settings.Path);
            var compress   = settings.Compress ? ", COMPRESSION" : string.Empty;

            using (var connection = SqlServerAliasesImpl.OpenSqlConnection(context, connectionString))
            {
                context.Log.Information($"Backing up database '{databaseName}' to {backupFile}");

                var sql = $@"
                    BACKUP DATABASE {Sql.EscapeName(databaseName)}
                    TO DISK = @backupFile
                    WITH FORMAT, INIT, COPY_ONLY, NAME = '{databaseName} Full Backup',
                    SKIP, REWIND, NOUNLOAD, STATS = 10 {compress}";

                context.Log.Information(sql);

                var command = SqlServerAliasesImpl.CreateSqlCommand(sql, connection);
                command.Parameters.AddWithValue("@backupFile", backupFile);
                command.ExecuteNonQuery();
            }
        }
        private static SqlCommand GetSetDatabaseSingleUserModeCommand(ICakeContext context, SqlConnection connection, String databaseName, bool singleUserMode)
        {
            var sb = new StringBuilder();

            sb.AppendLine();

            if (singleUserMode)
            {
                sb.AppendLine($@"if db_id({Sql.EscapeNameQuotes(databaseName)}) is not null");
                sb.AppendLine($@"begin");
                sb.AppendLine($@"    use master;");
                sb.AppendLine($@"    alter database {Sql.EscapeName(databaseName)} set single_user with rollback immediate;");
                sb.AppendLine($@"end");
                sb.AppendLine($@";");
            }
            else
            {
                sb.AppendLine($@"if db_id({Sql.EscapeNameQuotes(databaseName)}) is not null");
                sb.AppendLine($@"begin");
                sb.AppendLine($@"    use master;");
                sb.AppendLine($@"    alter database {Sql.EscapeName(databaseName)} set multi_user;");
                sb.AppendLine($@"end");
                sb.AppendLine($@";");
            }

            context.Log.Debug($"Executing SQL : {sb}");
            var command = SqlServerAliasesImpl.CreateSqlCommand(sb.ToString(), connection);

            return(command);
        }
Ejemplo n.º 5
0
 private static string ReadSingleString(string sql, string columnName, SqlConnection connection)
 {
     using (var command = SqlServerAliasesImpl.CreateSqlCommand(sql, connection))
     {
         return(ReadSingleString(command, columnName));
     }
 }
Ejemplo n.º 6
0
        internal static String GetDatabaseName(FilePath backupFile, SqlConnection connection)
        {
            var sql     = @"restore headeronly from disk = @backupFile";
            var command = SqlServerAliasesImpl.CreateSqlCommand(sql, connection);

            command.Parameters.AddWithValue("@backupFile", backupFile.ToString());

            var dbName = ReadSingleString(command, "DatabaseName");

            return(dbName);
        }
Ejemplo n.º 7
0
        internal static string GetDatabaseName(FilePath backupFile, SqlConnection connection)
        {
            const string sql = "restore headeronly from disk = @backupFile";

            using (var command = SqlServerAliasesImpl.CreateSqlCommand(sql, connection))
            {
                command.Parameters.AddWithValue("@backupFile", backupFile.ToString());

                return(ReadSingleString(command, "DatabaseName"));
            }
        }
Ejemplo n.º 8
0
        private static SqlCommand GetSetDatabaseUserModeCommand(ICakeContext context, SqlConnection connection, string databaseName, DbUserMode userMode)
        {
            var sb = new StringBuilder();

            sb.AppendLine();

            switch (userMode)
            {
            case DbUserMode.SingleUser:
                sb.Append("if db_id(").Append(Sql.EscapeNameQuotes(databaseName)).AppendLine(") is not null");
                sb.AppendLine("begin");
                sb.AppendLine("    use master;");
                sb.Append("    alter database ").Append(Sql.EscapeName(databaseName)).AppendLine(" set single_user with rollback immediate;");
                sb.AppendLine("end");
                sb.AppendLine(";");
                break;

            case DbUserMode.RestrictedUser:
                sb.Append("if db_id(").Append(Sql.EscapeNameQuotes(databaseName)).AppendLine(") is not null");
                sb.AppendLine("begin");
                sb.AppendLine("    use master;");
                sb.Append("    alter database ").Append(Sql.EscapeName(databaseName)).AppendLine(" set restricted_user with rollback immediate;");
                sb.AppendLine("end");
                sb.AppendLine(";");
                break;

            default:
                sb.Append("if db_id(").Append(Sql.EscapeNameQuotes(databaseName)).AppendLine(") is not null");
                sb.AppendLine("begin");
                sb.AppendLine("    use master;");
                sb.Append("    alter database ").Append(Sql.EscapeName(databaseName)).AppendLine(" set multi_user;");
                sb.AppendLine("end");
                sb.AppendLine(";");
                break;
            }

            context.Log.Debug($"Executing SQL : {sb}");
            var command = SqlServerAliasesImpl.CreateSqlCommand(sb.ToString(), connection);

            return(command);
        }
        // This method is used to determine one single "Restore database" command.
        private static SqlCommand GetRestoreSqlBackupCommand(
            ICakeContext context,
            SqlConnection connection,
            int?backupSetFile,
            bool withReplace,
            bool withNoRecovery,
            string newDatabaseName,
            DirectoryPath newStorageFolder,
            params FilePath[] backupFiles)
        {
            var firstBackupFile = backupFiles.First();
            var oldDbName       = GetDatabaseName(firstBackupFile, connection);
            var databaseName    = newDatabaseName ?? oldDbName;

            context.Log.Information($"Using database name '{databaseName}' to be a name for the restored database");

            var logicalNames = GetLogicalNames(firstBackupFile, connection);

            var sb = new StringBuilder();

            sb.AppendLine();
            sb.AppendLine($"Restore database {Sql.EscapeName(databaseName)}");
            sb.AppendLine($"from");
            for (var i = 0; i < backupFiles.Length; i++)
            {
                // only need comma before penultimate list
                var trailingComma = i < backupFiles.Length - 1 ? "," : "";
                sb.AppendLine($"  disk = @backupFile{i}{trailingComma}");
            }
            sb.AppendLine($"with");
            if (backupSetFile.HasValue)
            {
                sb.AppendLine($"  file = {backupSetFile.Value},");
            }

            for (var i = 0; i < logicalNames.Count; i++)
            {
                sb.AppendLine($"  move @LName{i} to @LPath{i},");
            }

            if (withReplace)
            {
                sb.AppendLine($"  replace,");
            }

            if (withNoRecovery)
            {
                sb.AppendLine($"  norecovery");
            }
            else
            {
                sb.AppendLine($"  recovery");
            }
            context.Log.Debug($"Executing SQL : {sb}");

            var pathSeparator = GetPlatformPathSeparator(connection);
            var command       = SqlServerAliasesImpl.CreateSqlCommand(sb.ToString(), connection);

            for (var i = 0; i < backupFiles.Length; i++)
            {
                command.Parameters.AddWithValue($"@backupFile{i}", backupFiles[i].ToString());
            }
            for (var i = 0; i < logicalNames.Count; i++)
            {
                var lParameterName = "@LName" + i;
                context.Log.Debug($"Adding parameter '{lParameterName}' with value '{logicalNames[i].LogicalName}'");
                command.Parameters.AddWithValue(lParameterName, logicalNames[i].LogicalName);

                var filePath      = GetFilePath(connection, oldDbName, databaseName, newStorageFolder, logicalNames[i], pathSeparator);
                var pathParamName = "@LPath" + i;
                context.Log.Debug($"Adding parameter '{pathParamName}' with value '{filePath}'");
                command.Parameters.AddWithValue(pathParamName, filePath);
            }

            return(command);
        }