Jak ustalić, czy wyjątek jest określonego typu

82

Mam kod catch:

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

W przypadku tego fragmentu kodu próbuję wstawić rekord do bazy danych: dba skonfigurował go tak, że baza danych sprawdza, czy istnieją duplikaty i zwraca błąd, jeśli są duplikaty. Obecnie jak widać dodam ten sam błąd do modelu bez względu na to jaki błąd wystąpił. Chcę, żeby to się zmieniło, więc ten błąd jest dodawany do modelu tylko wtedy, gdy został spowodowany przez zduplikowany błąd ustawiony przez dba.

Poniżej znajduje się błąd, który chcę wyłapać. Zauważ, że jest to wewnętrzny wyjątek. Czy ktoś może mi powiedzieć, jak konkretnie to złapać?

wprowadź opis obrazu tutaj

AnonyMouse
źródło
1
Zobacz odpowiedź Davide. Ogólnie rzecz biorąc, łowienie Exceptionnie jest najlepszą praktyką. Powinieneś być tak dokładny, jak to tylko możliwe i pozwolić, aby wszystko, z czym nie możesz sobie poradzić, dotarło do użytkownika / struktury.
Ryan,
1
Sprawdź tę odpowiedź: stackoverflow.com/questions/3967140/…
Rob Packwood,

Odpowiedzi:

141

przed twoim bieżącym połowem dodaj:

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

W języku C # 6 możesz wykonać następujące czynności:

catch(DbUpdateException ex) when (ex.InnerException is UpdateException)
{
    // do what you want with ex.InnerException...
}
Davide Piras
źródło
3
czy istnieje haczyk składni „kiedy nie”?
conterio
4
@conteriocatch(DbUpdateException ex) when (!(ex.InnerException is UpdateException))
Tom
16

Zamień na System.Threading.ThreadAbortExceptionswój wyjątek.

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
źródło
3

Aby uzyskać nazwę wyjątku, możesz użyć

    catch (Exception exc){
       if (exc.GetType().FullName == "Your_Exception") 
       {
          // The same can be user for InnerExceptions
          // exc.InnerException.GetType().FullName
       }
   }
Uday Desiraju
źródło
2
Porównywanie typu wyjątku według łańcucha jest niebezpieczne. Niefortunny błąd w pisowni uczyni wyjątek dotyczący koszmaru!
Tejas Pendse
Zgoda. Porównaj typ z typem. exc.GetType () == typeof (YourException)
Lee Oades
2

Za mało przedstawiciela do komentowania. W odpowiedzi na pytanie @conterio (w odpowiedzi @Davide Piras):

czy istnieje haczyk składni „kiedy nie”?

Jest.

catch (Exception e) when (!(e is ArgumentException)) { }
Jason
źródło
-3

Możesz rzucić okiem na klasę SQLException - i sprawdzić zawartość komunikatu o wyjątku, jeśli zawiera on to, co teraz widzisz w swoim wewnętrznym wyjątku… Coś takiego:

try
{
    //your code here
}
catch (SQLException ex)
{
    if (ex.Message.Contains("Cannot insert duplicate key in obj...."))
    {
        //your code here
    }
}
Ann BG
źródło
1
Wątpię, czy SqlException jest generowany bezpośrednio, ale tylko jako wyjątek wewnętrzny. Ponadto prawdopodobnie lepiej byłoby sprawdzić numer błędu niż porównywać go z treścią komunikatu.
John Saunders,
Tak, możesz również sprawdzić numer błędu. Dziękuję za komentarz.
Ann BG
Jak porównać numer błędu? Nie jestem nawet pewien, jaki to numer, ponieważ jest to naprawdę konkretny błąd?
AnonyMouse,