Estou tentando restaurar o banco de dados de um backup completo ( .fbk
) e um backup rápido ( .qbk
). Nessa sequência, quando se trata de
USE MASTER
RESTORE DATABASE [" + DB_NAME + "]
FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
declaração, o banco de dados está travado no estado de recuperação.
Ao ver a exceção interna, ele diz
ALTER DATABASE não é permitido enquanto um banco de dados está no estado de Restauração.
A instrução ALTER DATABASE falhou.
Quando abro o SSMS, ele diz "Restaurando" no banco de dados.
Entretanto, quando tento apenas a .fbk
opção de backup completo ( ), ele restaura bem (nesse caso, está usando "Com recuperação").
Veja a condição else if no método WriteFile.
private void WriteFile()
{
try
{
// Creates Restore.sql file.
string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";
FileInfo File = new FileInfo(strTSQLFile);
StreamWriter Writer = File.CreateText();
// Write open database
string strTemp;
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
Writer.WriteLine("Go");
if (Complete_Opt.Checked == true) // Full restore
{
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
}
else if (Differential_Opt.Checked == true) // Quick restore
{
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("GO");
Writer.WriteLine("WAITFOR DELAY '00:00:10'");
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
Writer.WriteLine("Go");
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
}
Writer.WriteLine("GO");
Writer.WriteLine("ALTER DATABASE [" + DB_NAME + "] SET MULTI_USER");
Writer.WriteLine("GO");
Writer.WriteLine("USE PharmSpecDB");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestResults')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_TestResults");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_TestResults ON tblTestResults WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_SampleIDParameter')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_SampleIDParameter");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_SampleIDParameter ON tblSampleIDParameter WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_TestRun')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_TestRun");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_TestRun ON tblTestRun WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ReviewApprove')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ReviewApprove");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ReviewApprove ON tblReviewApprove WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActiveParamValues')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ActiveParamValues");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ActiveParamValues ON tblActiveParamValues WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("IF EXISTS (SELECT * FROM sys.triggers WHERE name = 'D_TRG_ActivityLogger')");
Writer.WriteLine("BEGIN");
Writer.WriteLine("DROP TRIGGER D_TRG_ActivityLogger");
Writer.WriteLine("END");
Writer.WriteLine("GO");
Writer.WriteLine("CREATE TRIGGER D_TRG_ActivityLogger ON tblActivityLogger WITH ENCRYPTION INSTEAD OF DELETE AS BEGIN raiserror (50003,14,1) END");
Writer.WriteLine("GO");
Writer.WriteLine("EXEC sp_revokedbaccess 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_grantdbaccess 'PharmSpecUsr','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_owner','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_accessadmin','PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_datareader' ,'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_datawriter ', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_ddladmin', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_securityadmin', 'PharmSpecUsr'");
Writer.WriteLine("EXEC sp_addrolemember 'db_backupoperator','PharmSpecUsr'");
Writer.WriteLine("GO");
Writer.Close();
}
catch (Exception Exc)
{
throw Exc;
}
}
Estou executando este SQL a partir do código C# da seguinte maneira:
try
{
string strTSQLFile = Environment.CurrentDirectory + "\\Restore.sql";
if (!File.Exists(strTSQLFile))
{
throw new FileNotFoundException();
}
using (StreamReader srSQL = new StreamReader(strTSQLFile))
{
string sqlLine;
StringBuilder sqlString = new StringBuilder();
while (!srSQL.EndOfStream)
{
sqlLine = srSQL.ReadLine();
if (string.IsNullOrEmpty(sqlLine) == false)
{
// We don't actually execute the "GO" lines but can use them to determine when to call the executenonquery function
if (string.Compare(sqlLine, "GO", true) == 0)
{
// Make sure we have something to execute
if (string.IsNullOrEmpty(sqlString.ToString()) == false)
{
ServerActionResult.ConnectionContext.ExecuteNonQuery(sqlString.ToString());
System.Diagnostics.Debug.WriteLine(sqlString);
}
sqlString.Clear();
}
// Add the next line to the stringbuilder object
else
{
sqlString.AppendLine(sqlLine);
}
}
}
}
}
catch (Exception exc)
{
throw exc;
}
Depuração:
Ao dizer System.Diagnostics.Debug.WriteLine(sqlString);
isso imprime:
ALTER DATABASE [PharmSpecDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
USE MASTER RESTORE DATABASE [PharmSpecDB] FROM DISK = 'C:\PharmBackup\Backup\PharmSpecDB_13-Nov-2024-12-42-57-717_Full.Fbk' WITH NORECOVERY
WAITFOR DELAY '00:00:10'
EDITAR:
Com este comentário e o que ele diz online "Para restaurar o banco de dados e colocá-lo online para que os usuários possam se conectar, você pode usar a instrução RESTORE DATABASE com a opção WITH RECOVERY". Estou tentando algo assim,
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + BackupFile_Txt.Text + "\' WITH NORECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");
strTemp = "USE MASTER RESTORE DATABASE [" + DB_NAME + "] FROM DISK = \'" + txt_Quick.Text + "\' WITH RECOVERY";
Writer.WriteLine(strTemp);
Writer.WriteLine("Go");
Fazer isso é reclamar,
"O backup de log ou diferencial não pode ser restaurado porque nenhum arquivo está pronto para avanço.\r\nRESTORE DATABASE está sendo encerrado de forma anormal.\r\nContexto do banco de dados alterado para 'master'."
Você já tentou isso?
Banco de dados travado no estado "Restaurando"
Provavelmente a solução para o problema,
é...