2012-02-26 5 views
1

キャンセルボタンをユーザに提供して、進行中のリストアを中止します。これを行うには、Restore.PercentCompleteイベントハンドラで、ユーザが[キャンセル]ボタンをクリックしてRestore.Abort()を呼び出したかどうかを確認します。しかし、これは助けない:リストアDBを中止できません

を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

ブレークポイントを入れて、 'CompletionStatusInPercent'が(それがあるべき)多くの場合、ヒットした場合、また_CancelRestore'この'に 'volatile'キーワードを追加してくださいは、任意のCPUを無効にする必要がありますboolのキャッシュとboolの実際の値を確認するスレッドを強制します(これは保証されていませんが)。 – oleksii

+0

hi @oleksii。揮発性のためにありがとう。ブレークポイントはそこにあり、きちんと訪問されます。私が推測する問題はSMOのどこかにあります。バックアップ/復元の作業例が必要です。 –

+0

キルのものをコメントアウトする!あなたはそれを一緒に戻す時間を与えていません! –

答えて

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; 
} 
関連する問題