2012-02-26 55 views
1

我想向用户提供取消按钮 - 中止正在进行的恢复。为此,请在Restore.PercentComplete事件处理程序中检查用户是否单击了取消按钮并调用Restore.Abort()。但是,这并不能帮助:无法中止恢复数据库

的SMO引发异常:

还原失败服务器 'MICHAEL7'。
执行Transact-SQL语句或批处理时发生异常。
堆栈跟踪:在Microsoft.SqlServer.Management.Smo.Restore.SqlRestore(服务器srv)

数据库永远处于“恢复”模式。下面是相关代码:

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

把一个断点,看看'CompletionStatusInPercent'经常打(应该是),还添加了'volatile'关键字'_CancelRestore'这应该禁用任何CPU为bool缓存并强制线程检查bool的实际值(尽管这不能保证)。 – oleksii 2012-02-26 10:43:42

+0

hi @oleksii。感谢波动。断点在那里,并被访问正常。我想这个问题是在SMO的某处。我需要一个备份/恢复中止的工作示例。 – 2012-02-26 13:03:08

+0

评论杀死的东西!你没有时间让自己回到一起! – 2012-03-12 15:16:26

回答

0

我知道这是一个老问题,但我被困在同样的问题,我找到了一个适合我的解决方案。

相反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; 
}