2010-04-08 11 views
68

Ho iniziato a usare try catch blocks (un po 'tardi, lo so!), Ma ora non sono sicuro di cosa fare con l'eccezione una volta che l'ho preso. Cosa dovrei fare?Ho preso un'eccezione !! Ora cosa?

Try 
    connection.Open() 
    Dim sqlCmd As New SqlCommand("do some SQL", connection) 
    Dim sqlDa As New SqlDataAdapter(sqlCmd) 
    sqlDa.Fill(dt) 
Catch ex As SQLException 
    ' Ahhhh, what to do now!!!? 
Finally 
    connection.Close() 
End Try 
+0

sembra che tu ritenga obbligatorio aggiungere try/catch ovunque. Forse puoi condividere con noi ciò che sai di questa affermazione in modo da poter chiarire il concetto. –

+71

prendi un barattolo di vetro e fai dei buchi nel coperchio ;-) –

+27

Eccezioni: devi prenderli tutti! – CiscoIPPhone

risposta

23

Cosa vuoi che faccia? Dipende interamente dalla tua applicazione.

Si potrebbe avere riprovare, è possibile visualizzare un MessageBox sullo schermo, scrivere su un registro, le possibilità sono infinite.

In qualità di sviluppatore non è possibile prevedere ogni possibile errore. È una buona idea avere codice di cattura generico anche se non sai come correggere l'errore. Si potrebbe salvare su un database e si potrebbe verificare uno dei 50 errori del database e non sarà possibile scrivere codice per gestirne ogni singolo.

Si dovrebbe inserire un catch generico per assicurarsi che il proprio programma non sia semplicemente crash, e in alcuni casi è sufficiente visualizzare l'errore e lasciargli fare un altro tentativo è sufficiente. Immagina se la causa fosse "il disco è pieno". Potresti semplicemente stampare l'eccezione e consentire all'utente di riprovare: saprebbero cosa fare e risolvere il problema da soli.

Questo è il motivo non sono d'accordo con il commento di non toccarla se non si sa cosa fare. Dovresti sempre gestirlo, anche se è solo per visualizzare un messaggio che dice "Errore", perché è infinitamente migliore di "Questo programma ha eseguito un'operazione illegale e sarà chiuso."

+0

Vorrei anche raccomandare di ridurre la quantità di codice all'interno del blocco, specialmente nell'esempio sopra. Sei a) connettendo a un database eb) eseguendo un comando SQL, entrambi possono sollevare molte eccezioni. Metti ognuno in un try try separato (o analizza la tua ex/eccezione) in modo da avere un'idea migliore di quale tipo di errore hai a che fare (ti sei fatto un pugno negli occhi o sei stato timbrato sul piede?) – CResults

+0

Potresti anche terminare l'applicazione in quanto l'eccezione è fatale –

+1

@Victor Hurdugaci quell'eccezione non è fatale, a meno che il programma richieda che i dati siano in esecuzione. Cerco sempre di non terminare il programma perché normalmente puoi lasciare che l'utente riprovi, riprova, fagli sapere che qualcosa non va, che l'utente sappia cosa fare. Non mi piacciono i programmi che ho usato solo per spegnere. – msarchet

0

vorrei prendere in considerazione la registrazione che l'eccezione ha avuto luogo e informare l'utente che si è riusciti a completare la loro richiesta. Ciò presuppone che questa richiesta SQL sia necessaria al completamento dell'azione che l'utente sta tentando di eseguire.

0

Dipende interamente dal contesto. Le opzioni possibili includono "Usa dati predefiniti invece dei dati dal database" e "Visualizza un messaggio di errore per l'utente".

0

Se non si vuole fare qualsiasi cosa con esso, si può sempre e solo fare try/finally piuttosto che try/catch/finally

9

Dipende da ciò che il sql fa davvero. È qualcosa:

  • che l'utente ha fatto? Forse creare un account o un messaggio - allora avete bisogno di informare l'utente che qualcosa non va
  • che l'applicazione fa naturalmente? Ti piace pulire i registri o qualcosa di simile? È fatale? L'applicazione può continuare? È qualcosa che può essere ignorato - forse ritentato? Dovrebbe essere annunciato l'amministratore?

Inizia con queste domande, che di solito portare a risposte su come trattare le eccezioni

5

A meno che non ti aspettavi l'errore (l'API dice che può occurr) e in grado di gestire (non v'è un passo ovvio da prendere se si verifica l'eccezione), probabilmente si desidera arrestare lo con molto rumore. Questo dovrebbe accadere durante il test/debug, in modo che il bug possa essere corretto prima che l'utente lo veda!

Naturalmente, come i commentatori hanno sottolineato, l'utente non dovrebbe mai vedere veramente tutto questo rumore. Un alto livello try/catch o qualche altro metodo (EMLAH, ho sentito per i progetti web .net) può essere usato per mostrare all'utente un bel messaggio di errore ("Oops! Qualcosa è andato storto!Cosa diavolo stavi cercando di fare? ") Con un pulsante di invio ...

Quindi, in sostanza, il mio punto è questo: Non rilevare errori che non sai come gestire! (tranne che per l'alto -level handler). Crash presto e con quante più informazioni possibili. Ciò significa che dovreste accedere alla pila e altre informazioni vitali chiamata, se a tutto il possibile per il debug.

+3

D'altra parte, mai "crash con molto rumore" mai prima degli occhi dell'utente. Dì qualcosa come "Ops, qualcosa è andato storto, ci stiamo lavorando.". Nessun dettaglio da vedere in pubblico. –

+4

Meglio per visualizzare una pagina personalizzata con un "per favore dicci cosa stavi facendo" casella di testo e pulsante di invio, in modo che possano sfogare. Ovviamente, non collegarlo a nulla. – NibblyPig

2

Se non si sa come reagire ad essa , non intercettare l'eccezione.

cattura invece in un luogo dove si ha la possibilità di gestire la cosa e dove si sa come continuare l'esecuzione di un fterwards.

1

In primo luogo, se l'applicazione non è in grado di gestire l'eccezione, in primo luogo non è necessario rilevarla (logging can be done via exception event handlers without catching).

Se c'è qualcosa che si può fare allora farlo. Ad esempio, ripristinare la transazione e segnalare che non è riuscita all'utente. Questo dipenderà dalla tua applicazione.

20

dipende dalla vostra logica di business, ma si consiglia di fare una o più delle seguenti operazioni.

  • rollback la transazione
  • registrare l'errore
  • Alert qualsiasi utente dell'applicazione
  • Ripetere l'operazione
  • rigenerare l'eccezione

Puoi anche controllare se il l'eccezione è di un tipo che è possibile gestire prima di uno dei precedenti.

Un buon articolo sulla gestione delle eccezioni VB.NET è Exception Handling in VB.NET di Rajesh VS.

+0

Suggerisco almeno i primi tre per la maggior parte degli errori SQL. – HLGEM

64

Regola generale per la gestione delle eccezioni - Se non sai cosa fare con esso, non prenderlo.

Corrollary alla regola generale per la gestione delle eccezioni - gestire le eccezioni all'ultimo momento responsabile. Se non sai se questo è l'ultimo momento responsabile, non lo è.

+2

Non sono d'accordo con questo e ho modificato la mia risposta per riflettere sul perché. – NibblyPig

+1

+1 - e .. Se non puoi fare nulla di utile qui, non prenderlo qui. –

+0

@ SLC - penso che tu stia interpretando male la risposta. Ovviamente la tua applicazione non dovrebbe bloccarsi in modo blando a causa di un'eccezione non gestita e un gestore di livello app di solito è una buona idea. Cattura un'eccezione solo perché puoi anticipare che non sempre il miglior design. –

2

Una cosa da tenere a mente è che nelle sezioni in cui si sente che non si desidera utilizzare un try/catch, si dovrebbe spostare le istruzioni Dim fuori del blocco try. È possibile assegnare loro valori all'interno del blocco, ma se li si definisce all'interno del blocco try, non si avrà accesso a tali variabili all'interno della sezione catch in quanto saranno fuori ambito in quel punto.

La mia pratica standard in blocchi catch, inclusa la possibilità di correggere l'errore se possibile, è scrivere a qualsiasi meccanismo di registrazione che sto utilizzando le informazioni sulle variabili chiave coinvolte nella sezione che causa l'errore. Non è necessario, ma ho trovato che aiuta spesso con i problemi di debug.

1

FYI, non c'è bisogno di usare la cattura di avere un finally.

A volte le persone lanciare una nuova eccezione che è più firendly e aggiungere l'eccezione originale come l'eccezione interna.

Spesso questo viene utilizzato per registrare l'errore in un file o inviare una mail a un operatore.

A volte, specialmente con SQL, può significare solo una chiave duplicata che significa, per esempio, si prega di scegliere un altro nome utente, quello già preso - è tutto per la vostra applicazione.

2

Mi piacerebbe suggerirvi che se non sapete cosa fare con un'eccezione, non prenderla. Troppo spesso, i programmatori catturano le eccezioni e li inghiottono completamente.

catch (Exception ex) 
{ 
    /* I don't know what to do.. *gulp!* */ 
} 

Chiaramente questo non è buono, perché le cose brutte stanno accadendo e non viene intrapresa alcuna azione. Raccogli solo eccezioni che sono perseguibili!

Detto questo, la gestione degli errori aggraziata è importante. Non vuoi che la tua app si arresti, giusto? È possibile trovare ELMAH utile per le applicazioni Web e un gestore di eccezioni globale è piuttosto semplice da configurare per le app desktop WinForms o XAML.

Mettendo tutto insieme, si potrebbe trovare utile questa strategia: 1. rilevare le eccezioni specifiche che si possono verificare (DivideByZeroException, SQLException, ecc.) E allontanarsi dall'eccezione generica catch-all; 2. controrilanciare l'eccezione dopo averla gestita. per esempio.

catch (SQLException ex) 
{ 
    /* TODO: Log the error somewhere other than the database... */ 
    throw; // Rethrow while preserving the stack trace. 
} 

Cosa si può veramente fare con un SQLException? La connessione al database è scomparsa? È stata una brutta ricerca? Probabilmente non vuoi aggiungere tutta la logica di gestione per questo, e inoltre, cosa succede se è qualcosa che non ti aspetti? Quindi, gestisci l'eccezione, se possibile, controrilanciare a meno che tu non sia sicuro che sia risolto e gestirlo con garbo a livello (es. Mostra un messaggio del tipo "Qualcosa è andato storto, ma potresti Informazioni dettagliate: "[Es. messaggio]." Annulla o riprova? ")

HTH!

John Saunders, grazie per la correzione.

+2

Registrazione e re-lancio accurati. Se si accede a ciascun livello, si potrebbe finire con molte, molte voci della stessa eccezione nel registro degli errori. Google "log rethrow" per alcuni suggerimenti sulla giusta strada da percorrere. – WCWedin

+0

@JohnSaunders Dovresti considerare di cancellare il tuo commento ora che la risposta è stata corretta. –

+0

@ Marco: grazie. Non sapevo del cambiamento. Rimuovi downvot. –

14

Vedo un sacco di consigli per non prenderlo se non si sa cosa fare con esso. Questo è solo tipo di a destra. Dovresti prendere delle eccezioni, ma forse non a questo livello. Utilizzando il codice per fare un esempio, mi piacerebbe scrivere più in questo modo:

Using connection As New SqlConnection("connection string here"), _ 
     sqlCmd As New SqlCommand("do some SQL", connection), _ 
     sqlDa As New SqlDataAdapter(sqlCmd) 

    sqlDa.Fill(dt) 
End Using 

Non solo non c'è try/catch/finally, non c'è apertura o chiusura. La funzione .Fill() è documentata come apertura della connessione, se necessario, e il blocco Using renderà assolutamente certo che sia chiuso correttamente, anche se viene generata un'eccezione.

Questo lascia libero di rilevare eccezioni a un livello superiore — nell'interfaccia utente o nel codice aziendale che chiama la funzione su cui viene eseguita la query, anziché proprio qui alla query stessa. Questo codice di livello superiore si trova in una posizione molto migliore per prendere decisioni su come procedere, su quale registro deve essere eseguito o mostrare un messaggio di errore migliore all'utente.

In effetti, è questa capacità di eccezioni a "bollire" nel codice che le rende così preziose. Se rilevi sempre un'eccezione proprio là dove viene generata, le eccezioni non aggiungono molto valore oltre la vecchia sintassi "On Error Goto X" del vb.

0

A seconda del tipo di applicazione, prendere in considerazione un gestore di registrazione globale (ad esempio "Application_Error" per applicazioni ASP.NET) o un sistema di gestione delle eccezioni fornito da open source o MSFT pre-compilato.

Il Exception Handling Application Block come parte della Enterprise Library 5.0 è un framework suggerito da utilizzare.

Oltre alla registrazione, sono d'accordo sul fatto che le eccezioni non devono essere prese in modo esplicito a meno che non sia necessario fare qualcosa di significativo con loro. E il peggior errore è solo quello di "catturare" e poi "lanciare" di nuovo, poiché questo rovina lo StackTrace.

0

Bene, Questo dipende principalmente se si stanno facendo soldi dalla vostra applicazione o meno. Secondo la mia esperienza, nessuno (che ha pagato per un'applicazione) gradisce vederlo andare in crash e chiudersi, preferisce invece un breve messaggio esplicativo sull'errore e una seconda possibilità di continuare qualunque cosa stessero facendo più una possibilità di salvare/esportare i loro dati modificati. IMO una buona pratica è quella di catturare tutto ciò che può causare qualcosa di sbagliato fuori dal tuo controllo, come operazioni di I/O, attività connesse alla rete, e.t.c. e visualizzare un messaggio rilevante per l'utente. Nel caso in cui venga generata un'eccezione a causa di un errore relativo alla logica, è meglio non prenderla poiché ciò ti aiuterà a trovare e correggere l'errore effettivo.

Spero che questo aiuti.

Problemi correlati