Reputation: 159
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
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
Upvotes: 3
Views: 8005
Reputation: 2797
Additionally to marc-s's answer, you can solve the "database in use" error adding a single line of code right before .SqlRestore()
:
_server.KillAllPrecesses("MyDatabaseName");
res.SqlRestore(_server);
This simulate exactly the same behavior as Sql Server Management Studio restore:
Upvotes: 0
Reputation: 754478
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:
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);
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:
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.
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:
Upvotes: 7