3

我正在使用以下 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

关联

SMO 错误:

Microsoft.SqlServer.Management.Smo.FailedOperationException:服务器“MORTEZA”的还原失败。
---> Microsoft.SqlServer.Management.Smo.SmoException:
System.Data.SqlClient.SqlError:无法获得独占访问,因为数据库正在使用中。 在 Microsoft.SqlServer.Management.Smo.BackupRestoreBase.ExecuteSql (服务器服务器,StringCollection 查询)在 Microsoft.SqlServer.Management.Smo
的 Microsoft.SqlServer.Management.Smo.ExecutionManager.ExecuteNonQueryWithMessage(StringCollection 查询,ServerMessageEventHandler dbccMessageHandler,布尔错误AsMessages) 。 Restore.SqlRestore(服务器 srv)


在 RelationAtOfficeApp.Admin.AdministratorMainPage.Restore(String destinationPath) 在 E:\prozhe\RelationAtOfficeApp\RelationAtOfficeApp\RelationAtOfficeApp\Admin\AdministratorMainPage.xaml.cs:line 268

4

2 回答 2

7

最可能的原因是:

  • 您已从服务器备份 - 备份Data.mdfData_Log.ldf文件Backup.bak

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

在这种情况下,.mdfand.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);
    

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

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

  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. 如果您的数据库仍然连接到您的服务器,您可以使用Object ExplorerSQL Server Management Studio 中的 找出数据库的逻辑文件名是什么;右键单击您选择的数据库,然后您将看到此对话框,在该Files部分中,您将获得所需的信息:

在此处输入图像描述

于 2012-10-14T20:32:39.330 回答
0

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

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

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

在此处输入图像描述

于 2019-09-19T14:17:40.037 回答