So stellen Sie fest, ob eine Ausnahme von einem bestimmten Typ ist

81

Ich habe einen Versuchscode:

try 
{
    ...
}
catch(Exception ex) 
{
    ModelState.AddModelError(
        "duplicateInvoiceNumberOrganisation", "The combination of organisation and invoice number must be unique");
}

Für diesen Code versuche ich, einen Datensatz in eine Datenbank einzufügen: Die Datenbank hat ihn so eingerichtet, dass die Datenbank nach Duplikaten sucht und einen Fehler zurückgibt, wenn Duplikate vorhanden sind. Wie Sie sehen, füge ich dem Modell derzeit denselben Fehler hinzu, unabhängig davon, welcher Fehler aufgetreten ist. Ich möchte, dass es geändert wird, damit dieser Fehler nur dann zum Modell hinzugefügt wird, wenn er durch den von der dba eingerichteten doppelten Fehler verursacht wurde.

Unten ist der Fehler, den ich abfangen möchte. Beachten Sie, dass es sich um die innere Ausnahme handelt. Kann mir jemand sagen, wie ich diesen gezielt fangen soll?

Geben Sie hier die Bildbeschreibung ein

AnonyMouse
quelle
1
Siehe Davides Antwort. Im Allgemeinen ist das Fangen Exceptionkeine bewährte Methode. Sie sollten so spezifisch wie möglich sein und alles, was Sie nicht handhaben können, an den Benutzer / das Framework weitergeben.
Ryan
1
Überprüfen Sie heraus diese Antwort: stackoverflow.com/questions/3967140/…
Rob Packwood

Antworten:

141

Fügen Sie vor Ihrem aktuellen Fang Folgendes hinzu:

catch(DbUpdateException ex)
{
  if(ex.InnerException is UpdateException)
  {
    // do what you want with ex.InnerException...
  }
}

Ab C # 6 können Sie Folgendes tun:

catch(DbUpdateException ex) when (ex.InnerException is UpdateException)
{
    // do what you want with ex.InnerException...
}
Davide Piras
quelle
3
Gibt es eine Catch-Syntax "wenn nicht"?
Conterio
4
@conteriocatch(DbUpdateException ex) when (!(ex.InnerException is UpdateException))
Tom
15

Durch System.Threading.ThreadAbortExceptionIhre Ausnahme ersetzen .

try
{
    //assume ThreadAbortException occurs here
}
catch (Exception ex)
{
    if (ex.GetType().IsAssignableFrom(typeof(System.Threading.ThreadAbortException)))
    {
         //what you want to do when ThreadAbortException occurs         
    }
    else
    {
         //do when other exceptions occur
    }
}
Nishantha
quelle
3

Um den Namen der Ausnahme zu erhalten, können Sie verwenden

    catch (Exception exc){
       if (exc.GetType().FullName == "Your_Exception") 
       {
          // The same can be user for InnerExceptions
          // exc.InnerException.GetType().FullName
       }
   }
Uday Desiraju
quelle
2
Der Vergleich des Ausnahmetyps nach Zeichenfolge ist gefährlich. Ein unglücklicher Rechtschreibfehler macht die Ausnahmebehandlung zu einem Albtraum!
Tejas Pendse
Einverstanden. Vergleichen Sie den Typ mit einem Typ. exc.GetType () == typeof (YourException)
Lee Oades
2

Nicht genug Vertreter, um einen Kommentar abzugeben. Als Antwort auf die Frage @conterio (in der Antwort von @Davide Piras):

Gibt es eine Catch-Syntax "wenn nicht"?

Es gibt.

catch (Exception e) when (!(e is ArgumentException)) { }
Jason
quelle
-3

Sie können sich die SQLException-Klasse ansehen und nach dem Inhalt der Ausnahmemeldung suchen, wenn sie das enthält, was Sie jetzt in Ihrer inneren Ausnahme sehen. So etwas:

try
{
    //your code here
}
catch (SQLException ex)
{
    if (ex.Message.Contains("Cannot insert duplicate key in obj...."))
    {
        //your code here
    }
}
Ann BG
quelle
1
Ich bezweifle, dass SqlException direkt ausgelöst wird, aber nur als innere Ausnahme. Außerdem ist es wahrscheinlich besser, die Fehlernummer zu überprüfen, als sie mit dem Nachrichtentext zu vergleichen.
John Saunders
Ja, Sie können auch die Fehlernummer überprüfen. Danke für den Kommentar.
Ann BG
Wie prüft man gegen die Fehlernummer? Ich bin mir nicht mal sicher, wie die Nummer lautet, da es sich um einen wirklich spezifischen Fehler handelt.
AnonyMouse