2010-04-08 7 views
68

He empezado a usar bloques de captura de prueba (un poco tarde, lo sé), pero ahora no estoy seguro de qué hacer con la excepción una vez que la atrapé. ¿Que debería hacer?¡He atrapado una excepción! ¿Ahora que?

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

parece que cree que es obligatorio agregar try/catch en todas partes. Quizás puedas compartir con nosotros lo que sabes sobre esta declaración para que podamos aclarar el concepto. –

+71

obtener un frasco de vidrio y hacer algunos agujeros en la tapa ;-) –

+27

Excepciones: Tengo que atrapar a todos! – CiscoIPPhone

Respuesta

23

¿Qué desea que haga? Depende completamente de tu aplicación.

Puede hacer que vuelva a intentarlo, puede mostrar un cuadro de mensaje en la pantalla, escribir en un registro, las posibilidades son infinitas.

Como desarrollador no puede predecir todos los posibles errores. Es una buena idea tener código de captura genérico incluso si no sabes cómo solucionar el error. Podría estar guardando en una base de datos, y uno de los 50 errores de base de datos podría ocurrir, y no podrá escribir código para manejar cada uno.

Debe poner un enlace genérico para asegurarse de que su programa no se limite simplemente a crash, y en algunos casos simplemente es suficiente mostrar el error y permitirles realizar otra operación. Imagine si la causa era 'disco está lleno'. Simplemente podría imprimir la excepción y permitir que el usuario intente de nuevo: ellos sabrían qué hacer y resolverían el problema ellos mismos.

Es por eso que no estoy de acuerdo con el comentario sobre no manejarlo si no sabes qué hacer. Siempre debe manejarlo, incluso si es solo para mostrar un mensaje que dice 'Error', porque es infinitamente mejor que "Este programa ha realizado una operación ilegal y se cerrará".

+0

También recomendaría reducir la cantidad de código dentro de su bloque, especialmente en el ejemplo anterior. Está a) conectándose a una base de datos yb) ejecutando un comando SQL, los cuales pueden generar muchas excepciones. Ponga cada uno en una captura de prueba por separado (o analice su ex/excepción) para que tenga una mejor idea de qué tipo de error está tratando (¿le han perforado el ojo o le han estampado en el pie?) – CResults

+0

Podría también finaliza la aplicación ya que la excepción es fatal –

+1

@Victor Hurdugaci que la excepción no es fatal, a menos que el programa requiera que esos datos se estén ejecutando. Siempre trato de no finalizar el programa porque normalmente puede permitir que el usuario intente de nuevo, intente nuevamente, hágales saber que algo está mal, permita que el usuario sepa qué hacer. No me gustan los programas que he estado usando para apagar. – msarchet

0

Consideraría registrar que se produjo la excepción y notificar al usuario que no pudo completar su solicitud. Esto supone que esta solicitud de SQL es necesaria para completar la acción que el usuario intenta realizar.

0

Depende completamente del contexto. Las opciones posibles incluyen "Usar datos predeterminados en lugar de datos de la base de datos" y "Mostrar un mensaje de error para el usuario".

0

Si no quiere hacer nada con ella, siempre se puede simplemente tratar/fin en lugar de tratar/catch/finally

9

Depende de lo que el sql realmente. ¿Es algo:

  • que el usuario hizo? Tal vez cree una cuenta o un mensaje, entonces debe informar al usuario que algo está mal
  • que la aplicación lo hace de forma natural? ¿Como limpiar troncos o algo similar? ¿Es fatal? ¿Puede continuar la aplicación? ¿Es algo que se puede ignorar, quizás volver a intentar? ¿Debería anunciarse el administrador?

de inicio con estas preguntas, que por lo general conducen a respuestas acerca de cómo tratar excepciones

5

A menos que se esperaba el error (la API dice que puede occurr) y puede manejarlo (hay un paso obvio para tomar si se produce la excepción), es probable que desee bloquearse con mucho ruido. Esto debería ocurrir durante las pruebas/depuración, para que el error pueda solucionarse antes de que el usuario lo vea.

Por supuesto, como comentaron los comentaristas, el usuario nunca debería ver realmente todo este ruido. Se puede usar un alto nivel try/catch o algún otro método (EMLAH, que escucho para proyectos web .net) para mostrarle al usuario un mensaje de error agradable ("¡Vaya! ¡Algo salió mal!¿Qué demonios estabas tratando de hacer? ") Con un botón de enviar ...

Así que, básicamente, mi punto es este: ¡No capte los errores que no sabe cómo manejar! (excepto el alto manejador -level). Crash temprana y la mayor cantidad de información posible. Esto significa que debe conectarse la pila y otra información vital llamada si es posible para la depuración.

+3

Por otro lado, nunca "choque con mucho ruido" ante los ojos del usuario. Diga algo como "Ops, algo salió mal, estamos trabajando en eso". No hay detalles para ver en público. –

+4

Lo mejor es mostrar una página personalizada con un cuadro de texto "por favor díganos lo que estaba haciendo" y enviar, para que puedan ventilar. Por supuesto, no lo conecte a nada. – NibblyPig

2

Si no sabe cómo reaccionar a ella , no capte la excepción.

En vez de eso, acéptelo en un lugar donde tenga la posibilidad de manejarlo y donde sepa cómo continuar la ejecución. hacia adelante

20

Depende de la lógica de su empresa, pero es posible que desee hacer una o más de las siguientes acciones.

  • Rollback su transacción
  • registrar el error
  • Alerta cualquier usuario de la aplicación
  • Vuelva a intentar la operación
  • volver a lanzar la excepción

También es posible que desee comprobar si el la excepción es de un tipo que puede manejar antes de una de las anteriores.

Un buen artículo sobre el manejo de excepciones de VB.NET es Exception Handling in VB.NET de Rajesh VS.

+0

Sugiero al menos los tres primeros para la mayoría de los errores de SQL. – HLGEM

64

Regla de oro para el manejo de excepciones: si no sabes qué hacer con él, no lo captures.

Corolla a la regla de oro para el manejo de excepciones: maneje las excepciones en el último momento responsable. Si no sabe si este es el último momento responsable, no lo es.

+2

No estoy de acuerdo con esto, y he editado mi respuesta para reflejar por qué. – NibblyPig

+1

+1 - y ... Si no puede hacer nada útil al respecto aquí, no lo capte aquí. –

+0

@SLC: creo que está malinterpretando la respuesta. Por supuesto, su aplicación no debe fallar alegremente debido a una excepción no controlada, y un controlador de nivel de aplicación suele ser una buena idea. Captura una excepción solo porque puedes anticipar que uno no siempre es el mejor diseño. –

2

Una cosa a tener en cuenta es que en las secciones en las que sientes que quieres usar un try/catch, deberías mover tus sentencias Dim desde el bloque try. Puede asignarles valores dentro del bloque, pero si los define dentro del bloque try, no tendrá acceso a esas variables dentro de la sección catch ya que estarán fuera del alcance en ese punto.

Mi práctica habitual en catch blocks, que incluye tratar de remediar el error si es posible, es escribir en cualquier mecanismo de registro que esté utilizando información sobre variables clave que estuvieron involucradas en la sección que causa el error. No es necesario, pero he descubierto que a menudo ayuda con los problemas de depuración.

1

Para su información, no tiene que usar la captura para tener una declaración final.

A veces las personas lanzan una nueva excepción que es más fogosa y agrega la excepción original como la excepción interna.

A menudo esto se utiliza para registrar el error en un archivo o enviar un correo electrónico a un operador.

A veces, especialmente con SQL, puede significar simplemente una clave duplicada, lo que significa, por ejemplo, elegir otro nombre de usuario, ese ya está tomado, todo depende de su aplicación.

2

Me gustaría sugerirle que si no sabe qué hacer con una excepción, no la atrape. Con demasiada frecuencia, los codificadores detectan excepciones y simplemente las tragan enteras.

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

Claramente esto no es bueno, porque las cosas malas están sucediendo, y no se están tomando medidas. ¡Solo atrape excepciones que sean procesables!

Dicho esto, el manejo elegante de errores es importante. No quiero que tu aplicación se cuelgue, ¿verdad? Puede encontrar que ELMAH es útil para aplicaciones web, y un controlador de excepción global es bastante fácil de configurar para las aplicaciones de escritorio WinForms o XAML.

Poniendo todo junto, puede encontrar esta estrategia útil: 1. atrapar excepciones específicas que usted sabe que podrían ocurrir (DivideByZeroException, SQLException, etc.) y alejarse de la Excepción genérica catch-all; 2. vuelva a subir la excepción después de manejarlo. p.ej.

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

¿Qué se puede hacer con una SQLException? ¿Desapareció la conexión de la base de datos? ¿Fue una mala consulta? Probablemente no desee agregar toda la lógica de manejo para eso, y además, ¿qué pasa si es algo que no esperaba? Así que solo maneje la excepción si puede, vuelva a subir a menos que esté seguro de que se resuelva, y trátelo elegantemente en un nivel global (por ejemplo, muestre un mensaje como "Algo salió mal, pero es posible que pueda continuar trabajando.Información detallada: '[ex.Mensaje]'. Abortar o Reintentar? ")

¡HTH!

John Saunders, gracias por la corrección.

+2

Registro y relanzamiento cuidadosos. Si inicia sesión en cada nivel, puede terminar con muchas, muchas entradas de la misma excepción en su registro de errores. Google "volver a iniciar sesión" para obtener algunos consejos sobre el camino correcto a seguir. – WCWedin

+0

@JohnSaunders Debería considerar eliminar su comentario ahora que la respuesta ha sido resuelta. –

+0

@Mark: gracias. No sabía sobre el cambio. Vázquez eliminado. –

14

Veo muchas recomendaciones para no captarlo si no sabes qué hacer con él. Eso es solo tipo de derecha. Deberías estar atrapando excepciones, pero tal vez no en este nivel. Usando el código para un ejemplo, me gustaría escribir es de la misma familia:

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 

No sólo no hay try/catch/Por último, no hay apertura o cierre. La función .Fill() está documentada como la apertura de la conexión, si es necesario, y el bloque Using asegurará que esté cerrado correctamente, , incluso si se lanza una excepción.

Esto te deja libre para detectar excepciones en un nivel superior — en la UI o en el código comercial que llama a la función donde se ejecuta tu consulta, en lugar de hacerlo aquí mismo en la consulta. Este código de nivel superior se encuentra en una posición mucho mejor para tomar decisiones sobre cómo proceder, qué registro debe suceder o mostrar un mejor mensaje de error al usuario.

De hecho, es esta capacidad para que las excepciones "burbujeen" en su código que las hace tan valiosas. Si siempre atrapa una excepción allí donde se produce, las excepciones no agregan mucho más allá de la sintaxis anterior de vb "On Error Goto X".

0

Dependiendo del tipo de aplicación, considere un controlador de registro global (es decir, 'Application_Error' para aplicaciones ASP.NET) o el uso de un marco de manejo de excepciones preinstalado de código abierto o proporcionado por MSFT.

El Exception Handling Application Block como parte de Enterprise Library 5.0 es un marco sugerido para usar.

Además del registro, acepto que las excepciones no se deben capturar explícitamente a menos que necesite hacer algo significativo con ellas. Y el peor error es simplemente 'Atrapar' y luego 'Lanzar' de nuevo, ya que esto arruina el Registro de Apilamiento.

0

Bueno, Eso depende principalmente de si está ganando dinero con su aplicación o no. Según mi experiencia, a nadie (que pagó una aplicación) le gusta verla colgarse y cerrarse, prefieren un mensaje breve y explicativo sobre el error y una segunda oportunidad para continuar lo que sea que estén haciendo, más la posibilidad de guardar/exportar su datos modificados. IMO una buena práctica es atrapar todo lo que pueda hacer que algo incorrecto quede fuera de su control, como operaciones de E/S, tareas relacionadas con la red, e.t.c. y mostrar un mensaje relevante para el usuario. En caso de que se produzca una excepción debido a un error relacionado con la lógica, es mejor no detectarlo, ya que esto le ayudará a encontrar y corregir el error real.

Espero que esto ayude.

Cuestiones relacionadas