2012-02-26 3 views
1

진행중인 복원을 중단하기 위해 취소 버튼을 사용자에게 제공하고 싶습니다. 이렇게하려면 Restore.PercentComplete 이벤트 처리기에서 사용자가 취소 버튼을 클릭했는지 확인하고 Restore.Abort()을 호출합니다. 그러나 이것은 도움이되지 않습니다복원 DB를 중단 할 수 없음

은 서버 'MICHAEL7'에 대한 복원하지 못했습니다 :

SMO는 예외가 발생합니다.
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'가 (이 있어야한다) 자주 충돌하는 경우도에'volatile' 키워드를 추가 볼'이 어떤 CPU를 사용하지 않도록해야한다 _CancelRestore' bool에 대한 캐시와 bool의 실제 값을 확인하도록 스레드를 강제합니다 (이것이 보장되지는 않지만). – oleksii

+0

안녕하세요. 휘발성에 감사드립니다. 중단 점이 있고 괜찮습니다. 내가 추측하는 문제는 어딘가 SMO에있다. 백업/복원 중단의 실제 예가 필요합니다. –

+0

죽이기 물건을 주석 처리하십시오! 당신은 다시 자신을 되돌릴 시간을주지 않습니다! –

답변

0

나는 이것이 오래된 질문이라는 것을 알고 있지만, 같은 문제에 봉착했다. 그리고 나에게 맞는 해결책을 찾았다.

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의 나는 다음과 같은 사용합니다.

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; 
} 
관련 문제