Search code examples
wpfsql-serverc#-4.0restoresmo

SMO : Restore failed for Server '.'


I'm using the following SMO code trying to restore a SQL Server database:

Server _server;
ServerConnection _conn;

public void Restore(string destinationPath)
{
   Restore res = new Restore();
   _conn = new ServerConnection { ServerInstance = "." };
   _server = new Server(_conn);

   try
   {
       string fileName = destinationPath;
       const string databaseName = "RelationAtOffice";

       res.Database = databaseName;
       res.Action = RestoreActionType.Database;
       res.Devices.AddDevice(fileName, DeviceType.File);

       res.PercentCompleteNotification = 10;
       res.ReplaceDatabase = true;
       res.PercentComplete += new PercentCompleteEventHandler(ProgressEventHandler);
       res.SqlRestore(_server);

       System.Windows.Forms.MessageBox.Show("Restore of " + databaseName + " Complete!", "Restore", MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
    catch (SmoException exSMO)
    {
       System.Windows.Forms.MessageBox.Show(exSMO.ToString());
    }
    catch (Exception ex)
    {
        System.Windows.Forms.MessageBox.Show(ex.ToString());
    }
}

Why the code the following link to the correct answer. But my code is not working? Code like together. I used the wpf and following link user the winapp

Link

SMO error :

Microsoft.SqlServer.Management.Smo.FailedOperationException: Restore failed for Server 'MORTEZA'.
---> Microsoft.SqlServer.Management.Smo.SmoException:
System.Data.SqlClient.SqlError: Exclusive access could not be obtained because the database is in use.
at Microsoft.SqlServer.Management.Smo.ExecutionManager.ExecuteNonQueryWithMessage(StringCollection queries, ServerMessageEventHandler dbccMessageHandler, Boolean errorsAsMessages)
at Microsoft.SqlServer.Management.Smo.BackupRestoreBase.ExecuteSql(Server server, StringCollection queries)
at Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(Server srv)
at RelationAtOfficeApp.Admin.AdministratorMainPage.Restore(String destinationPath) in E:\prozhe\RelationAtOfficeApp\RelationAtOfficeApp\RelationAtOfficeApp\Admin\AdministratorMainPage.xaml.cs:line 268


Solution

  • The most likely cause is this:

    • you've taken a backup from your server - backed up the Data.mdf and Data_Log.ldf into a Backup.bak file

    • on the same (server) machine, you're now trying to restore that same database

    In this case, the .mdf and .ldf should be overwritten - but that's not going to happen, because SQL Server still has that database under its control - so the restore fails, since the data and log file cannot be overwritten.

    There's two ways you can solve this:

    1. define "file relocations", e.g. define a new data and log file name upon restore. That way, your database now is restored, and the files are placed in the SQL Server data directory under a new name.

      This requires code something like his:

      ....  
      res.Devices.AddDevice(fileName, DeviceType.File);
      
      // define "file relocation" - for all "logical" files in a SQL Server database,
      // define a new physical location where the file will end up at          
      RelocateFile relocateDataFile = new RelocateFile("Data", @"(your data dir)\RestoredData.mdf");
      RelocateFile relocateLogFile = new RelocateFile("Log", @"(your log dir)\Data\RestoredData_log.ldf");
      
      res.RelocateFiles.Add(relocateDataFile);
      res.RelocateFiles.Add(relocateLogFile);
      
    2. If you don't want to create new files, you should be able to specify to SMO Restore that you want to replace the existing database with the restore operation, by setting:

      res.ReplaceDatabase = true;
      

      before calling

      res.SqlRestore(_server);
      

    Update: the logical file names that I used in the sample are of course just samples - in your case, your backup file most likely will contain other logical file names, and you need to use those file names in your code.

    You can find out what logical file names your database contains basically two ways:

    1. as the error message clearly stated - you can use the FILELISTONLY option on the RESTORE command in SQL Server Management Studio, thus inspecting the .bak file before you restore it. Try something like this:

      RESTORE FILELISTONLY
      FROM DISK = N'path-and-full-file-name-of-your-bak-file-here.bak'
      

      This will give you a small grid with the logical and physical file names contained in your .bak file.

    2. If you have the database still attached to your server, you can use the Object Explorer in SQL Server Management Studio to find out what the logical file names of your database are; right-click on your database of choice and then you'll see this dialog box, and in the Files section, you get the information you're looking for:

    enter image description here