我正在使用以下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: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行
答案 0 :(得分:7)
最可能的原因是:
您已从服务器进行备份 - 将Data.mdf
和Data_Log.ldf
备份到Backup.bak
文件中
在同一台(服务器)计算机上,您现在正在尝试恢复相同的数据库
在这种情况下,.mdf
和.ldf
应该被覆盖 - 但这不会发生,因为SQL Server仍然在其控制下拥有该数据库 - 因此恢复失败,因为数据和日志文件无法覆盖。
有两种方法可以解决这个问题:
定义“文件重定位”,例如在还原时定义新数据和日志文件名。这样,现在可以恢复您的数据库,并以新名称将文件放在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);
如果您不想创建新文件,则应该能够通过设置指定SMO Restore要将现有数据库替换为还原操作:
res.ReplaceDatabase = true;
之前打电话
res.SqlRestore(_server);
更新:我在示例中使用的逻辑文件名当然只是示例 - 在您的情况下,您的备份文件很可能包含其他逻辑文件名 ,您需要在代码中使用这些文件名。
您可以通过两种方式找出数据库包含的逻辑文件名:
正确显示错误消息 - 您可以在SQL Server Management Studio中的FILELISTONLY
命令上使用RESTORE
选项,从而在还原之前检查.bak
文件。尝试这样的事情:
RESTORE FILELISTONLY
FROM DISK = N'path-and-full-file-name-of-your-bak-file-here.bak'
这将为您提供一个小网格,其中包含.bak
文件中包含的逻辑和物理文件名。
如果数据库仍附加到服务器,则可以使用SQL Server Management Studio中的Object Explorer
来查找数据库的逻辑文件名;右键单击您选择的数据库,然后您将看到此对话框,并在Files
部分中获取您要查找的信息:
答案 1 :(得分:0)
除了marc-s的答案之外,您还可以解决在.SqlRestore()
之前添加一行代码的“正在使用的数据库”错误:
_server.KillAllPrecesses("MyDatabaseName");
res.SqlRestore(_server);
此模拟行为与Sql Server Management Studio还原完全相同: