SMO:服务器'还原失败。'

时间:2012-10-14 19:59:42

标签: wpf sql-server c#-4.0 restore smo

我正在使用以下SMO代码尝试还原SQL Server数据库:

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());
    }
}

为什么以下代码链接到正确的答案。但我的代码不起作用? 代码就像在一起。我使用wpf和以下链接用户winapp

Link

SMO错误:

  

Microsoft.SqlServer.Management.Smo.FailedOperationException:Restore   服务器'MORTEZA'失败。
  ---> Microsoft.SqlServer.Management.Smo.SmoException:
  System.Data.SqlClient.SqlError:无法获取独占访问权限   因为数据库正在使用中   在Microsoft.SqlServer.Management.Smo.ExecutionManager.ExecuteNonQueryWithMessage(StringCollection)   查询,ServerMessageEventHandler dbccMessageHandler,布尔值   errorsAsMessages)
  在Microsoft.SqlServer.Management.Smo.BackupRestoreBase.ExecuteSql(服务器   server,StringCollection查询)
  在Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(Server srv)
  在RelationAtOfficeApp.Admin.AdministratorMainPage.Restore(String   destinationPath)in   E:\ prozhe \ RelationAtOfficeApp \ RelationAtOfficeApp \ RelationAtOfficeApp \ Admin \ AdministratorMainPage.xaml.cs:第268行

2 个答案:

答案 0 :(得分:7)

最可能的原因是:

  • 您已从服务器进行备份 - 将Data.mdfData_Log.ldf备份到Backup.bak文件中

  • 在同一台(服务器)计算机上,您现在正在尝试恢复相同的数据库

在这种情况下,.mdf.ldf应该被覆盖 - 但这不会发生,因为SQL Server仍然在其控制下拥有该数据库 - 因此恢复失败,因为数据和日志文件无法覆盖。

有两种方法可以解决这个问题:

  1. 定义“文件重定位”,例如在还原时定义新数据和日志文件名。这样,现在可以恢复您的数据库,并以新名称将文件放在SQL Server数据目录中。

    这需要类似他的代码:

    ....  
    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. 如果您不想创建新文件,则应该能够通过设置指定SMO Restore要将现有数据库替换为还原操作:

    res.ReplaceDatabase = true;
    

    之前打电话

    res.SqlRestore(_server);
    
  3. 更新:我在示例中使用的逻辑文件名当然只是示例 - 在您的情况下,您的备份文件很可能包含其他逻辑文件名 ,您需要在代码中使用这些文件名。

    您可以通过两种方式找出数据库包含的逻辑文件名:

    1. 正确显示错误消息 - 您可以在SQL Server Management Studio中的FILELISTONLY命令上使用RESTORE选项,从而在还原之前检查.bak文件。尝试这样的事情:

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

      这将为您提供一个小网格,其中包含.bak文件中包含的逻辑和物理文件名。

    2. 如果数据库仍附加到服务器,则可以使用SQL Server Management Studio中的Object Explorer来查找数据库的逻辑文件名;右键单击您选择的数据库,然后您将看到此对话框,并在Files部分中获取您要查找的信息:

    3. enter image description here

答案 1 :(得分:0)

除了marc-s的答案之外,您还可以解决在.SqlRestore()之前添加一行代码的“正在使用的数据库”错误:

_server.KillAllPrecesses("MyDatabaseName");
res.SqlRestore(_server);

此模拟行为与Sql Server Management Studio还原完全相同:

enter image description here