我想为用户提供“取消”按钮 - 中止正在进行的恢复。为此,在Restore.PercentComplete
事件处理程序中,我检查用户是否单击了“取消”按钮并调用Restore.Abort()
。但这没有帮助:
SMO抛出异常:
服务器'MICHAEL7'的恢复失败。
执行Transact-SQL语句或批处理时发生异常
堆栈跟踪:在Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(服务器srv)
DB永远处于“恢复”模式。以下是相关代码:
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
private volatile bool _CancelRestore = false;
private Restore _RestoreDB;
private Server _myServer;
private Database _currentDatabase;
// user hits Cancel buttton
public void CancelRestore()
{
_CancelRestore = true;
}
// Restore.PercentComplete event handler
private static void CompletionStatusInPercent(object sender, PercentCompleteEventArgs args)
{
if (_CancelRestore)
{
_RestoreDB.Abort();
// Disable the kills to let some time to Abort()
// Stop all processes running on the _currentDatabase database
// _myServer.KillAllProcesses(_currentDatabase.Name);
// Stop the _currentDatabase database
// NOTE: it is a temp name DB: I do not restore over my application DB!
// _myServer.KillDatabase(_currentDatabase.Name);
}
else
{
Console.Clear();
Console.WriteLine("Percent completed: {0}%.", args.Percent);
}
}
备份/还原功能是在本文的帮助下实现的:SQL Server 2005 Database Backup and Restore using C# and .NET 2.0
感谢。
答案 0 :(得分:1)
我知道这是一个老问题,但我遇到了同样的问题,我发现了一个适合我的解决方案。
我使用以下内容代替KillDatabase:
sqlRestore.Abort();
sqlRestore.Wait(); //This will wait until the restore operation is canceled
Database db = _server.Database(databaseName);
if (db != null)
db.Drop(); // This will drop the "half" restored Database
应该说,我正在使用SqlRestoreAsync。
KillDatabase()会终止所有连接,所以KillAllProcesses()在这里已经过时了。
她是我的完整代码:
public async Task<bool> Restore(string backupFile, string databaseName, IProgress<int> progress, CancellationToken ct)
{
Restore sqlRestore = null;
bool result = await Task.Run(() =>
{
try
{
var deviceItem = new BackupDeviceItem(backupFile, DeviceType.File);
sqlRestore = new Restore
{
Action = RestoreActionType.Database,
Database = databaseName,
Partial = false,
ReplaceDatabase = true,
PercentCompleteNotification = 1
};
sqlRestore.PercentComplete += (s, e) => progress.Report(e.Percent);
sqlRestore.Devices.Add(deviceItem);
if (_server.Databases[databaseName] != null)
_server.KillAllProcesses(databaseName);
sqlRestore.SqlRestoreAsync(_server);
while (sqlRestore.AsyncStatus.ExecutionStatus == ExecutionStatus.InProgress)
{
ct.ThrowIfCancellationRequested();
Thread.Sleep(500);
}
if (sqlRestore.AsyncStatus.ExecutionStatus == ExecutionStatus.Succeeded)
{
Database db = _server.Databases[databaseName];
if (db != null)
db.SetOnline();
_server.Refresh();
return true;
}
return false;
}
catch (OperationCanceledException)
{
sqlRestore.Abort();
sqlRestore.Wait();
Database db = _server.Databases[databaseName];
if (db != null)
db.Drop();
return true;
}
catch (ConnectionFailureException)
{
return false;
}
catch (Exception ex)
{
_server.KillDatabase(databaseName);
return false;
}
}, ct);
return result;
}