2016-05-19 9 views
0

Ich habe das folgende Codefragment aus Klasse A, wo ich eine Async-Aktion für eine Datenbank ausführen und den InfoMessage-Ereignishandler abonnieren, um Informationsnachrichten von SQL abzufangen.Abfangen von Ausnahmen von einem Ereignishandler aus einer anderen Klasse

public void BackupDatabase(string DatabaseName, string BackupLocation, bool backupType = true) 
    { 
     //SQL for FULL database backup 
     string SQL = "BACKUP DATABASE [" + DatabaseName + "] TO DISK = N'" + BackupLocation + "\\" + DatabaseName +".bak' WITH FORMAT, NAME = N'" + DatabaseName + "-Full Database Backup', STATS = 1"; 

     using (SqlConnection db_conn = new SqlConnection(ConnectionString)) 
     { 

      UpdateStatusText("Establishing Connection to Database"); 
      db_conn.Open(); 
      db_conn.FireInfoMessageEventOnUserErrors = true; 
      db_conn.InfoMessage += BackupInfoMessages; 

      using (SqlCommand sqlCmd = new SqlCommand(SQL, db_conn)) 
      { 

       sqlCmd.ExecuteNonQuery(); 

      } 
      UpdateStatusText("Backup Complete."); 
     } 
    } 

    private void BackupInfoMessages(object sender, SqlInfoMessageEventArgs e) 
    { 
     foreach (SqlError info in e.Errors) 
     { 
      if(info.Class > 10) 
      { 
       logFile.ExMsg("Exception : " + e.Message); 
       throw new Exception(e.Message); 

      } 
      else 
      { 
       UpdateStatusText(e.Message, 1); 
      } 
     } 
    } 

In der Klasse B, ich bin mit einem Background, die eine Instanz der Klasse A verwendet „Backupdatabase“ in einem Try-Catch

try 
{ 
    DBOperations.BackupDatabase("DB","C:\\DBBackup\\DB.bak"); 
} 
catch (Exception ex) 
{ 

    logFile.ExMsg(ex.Message); 
    logFile.ExMsg(ex.StackTrace); 
    /* additional code to stop bgWorker */ 

} 

Je nach Schweregrad der Nachricht von SQL berichtet laufen , Ich werde es entsprechend behandeln, wenn eine Ausnahme von dort geworfen wird, fängt der BackgroundWorker nicht die Ausnahme ab, die von ClassA.BackupInfoMessages geworfen wird ... Ich habe versucht, meinen try/catch Block zu bewegen und einen in der BackupDatabase Methode ohne Glück hinzuzufügen . Es scheint, es einfach zu überspringen und es so zu behandeln, als ob keine Ausnahme geworfen wurde. Der Debugger in VS zeigt, dass eine System.Exception ausgelöst wurde, aber nichts betroffen ist. Fehle ich etwas oder mache ich etwas falsch? Vielen Dank!

+0

Ich habe für die ExecuteNonQuery() ausgewechselt. Danke für die Hilfe! – ephtee

+1

Ich löschte meine Antwort, weil ich sah, dass der aufrufende Code die Ausnahme wirklich hätte fangen sollen. Dass man es in VS sieht, aber nicht in der Calling-Methode gefangen wird, ist seltsam ... muss darüber nachdenken: - | – Clay

+0

Eine Sache, die Sie versuchen könnten, ist, die Ausnahme nicht im Hintergrund-Worker abzufangen, sondern mit ihr im RunWorkerCompleted-Ereignis des Mitarbeiters umzugehen. Wenn mehrere Threads im Spiel sind, ist dies möglicherweise der geeignetere Weg, um es zu fangen. – Clay

Antwort

1

Sie müssen an BackupInfoMessages denken, da es in seinem eigenen Hintergrundarbeiter läuft, deshalb versucht der Versuch/catch, es zu fangen, weil das Ereignis nicht im selben Aufrufstapel wie Ihr try/catch Block ist.

Sie benötigen eine andere Möglichkeit als direkt eine Ausnahme auszulösen, um zu vermitteln, dass ein Fehler aufgetreten ist.

Ich denke, aber bin nicht 100% sicher, dass alles Fehlerlevel 11 oder höher ExecuteNonQuery eine Ausnahme mit der Fehlerinfo werfen wird, so dass Sie die Ausnahme nicht manuell in Ihrem Event-Handler auslösen müssen. Die Einstellung .FireInfoMessageEventOnUserErrors = true kann dieses Verhalten jedoch ändern.

+0

Ich kenne keinen guten alternativen Weg, um die Fehlerinfo von meinem Kopf zu zeigen, aber wenn ich an einen denke, werde ich meine Antwort mit einem Beispiel aktualisieren. –

+0

Sie haben Recht in dieser Einstellung der '.FireInfoMessageEventOnuserErrors' auf false (oder entfernen es) wird eine Ausnahme auslösen und löst teilweise mein Problem. Auf der anderen Seite habe ich keine Möglichkeit, den Fortschritt des Backups an den Benutzer zu melden, ohne dass InfoMessages von SQL gesendet werden. – ephtee

+0

Ich habe einfach einen öffentlichen boolean zugewiesen, um zu überprüfen, ob der Prozess fehlgeschlagen ist und gegen den Schweregrad von SQL-Nachrichten getestet wurde, den booleschen Wert entsprechend zu ändern und dann den boolean nach der Abfrage zu testen und schließlich eine Ausnahme von BackupDatabase abhängig vom Ergebnis auszulösen . – ephtee

Verwandte Themen