Sie sind auf Seite 1von 4

Uso de RAISERROR desde SQL y gestin de errores desde ADO.

NET
Existen multitud de formas de manipular los errores o excepciones desde llamadas en cdigo administrado a procedimientos almacenados (SP en adelante) a travs de ADO.NET. Quizs la peculiaridad reside en la responsabilidad que le otorguemos a los SPs. Desde la versin SQL Server 2005, y con el uso de TRYCATCH podemos capturar y tratar un error de la siguiente forma.
BEGIN TRY ... END TRY BEGIN CATCH ... END CATCH

Sin embargo la no debemos olvidar el cmo devolvemos/notificamos un error desde el TRYCATCH a la llamada realizada desde cdigo administrado.

Devolver el error como resultado


Una opcin sera la de retornar la descripcin de las propiedades del error producido como resultado como sigue:
BEGIN TRY ... END TRY BEGIN CATCH ... SELECT ERROR_NUMBER() AS ErrorNumber, ERROR_SEVERITY() AS ErrorSeverity, ERROR_STATE() AS ErrorState, ERROR_PROCEDURE() AS ErrorProcedure, ERROR_LINE() AS ErrorLine, ERROR_MESSAGE() AS ErrorMessage; END CATCH

Esta forma devolver una fila de 6 columnas. El principal problema reside en que para la clase que realiza la llamada al SP le constar como que se ha ejecutado correctamente. Adems si la llamada se realiza mediante un DbCommand mediante ExecuteScalar nicamente se obtendr el nmero de error (primera columna). Por otro lado si el objetivo del SP es el de insertar, eliminar o modificar un conjunto de datos lo nico que deberamos esperar del SP es que nos dijera, en el caso que ha ido correcto, el nmero de filas afectadas, si se da el caso. En mi opinin, esta es una mala opcin y se debera obviar. Adems su deteccin desde la aplicacin cliente es confusa.

Devolver el error como mensaje y generar excepcin


La opcin ms correcta elegante es mediante el uso de RAISERROR dentro del CATCH. Sin embargo, para comprender el funcionamiento de esta funcin deberamos, en primer lugar, conocer la anatoma de un error en SQL Server.

Anatoma de un error
La informacin que obtenemos a travs del SQL Server Management Studio, en forma de texto es la interpretacin que ste hace de la informacin enviada por SQL Server a travs de varios componentes que establecen sus propiedades. Message number Cada error tiene un nmero identificativo. Los mensajes producidos por el usuario a travs de RAISERROR tienen un valor por defecto de 50000. A partir de 50001 en adelante se pueden configurar mensajes de error especficos en sys.messages.
USE master GO EXEC sp_addmessage @msgnum = 600001, @severity = 15, @msgtext = 'Indicated time %s is not allowed. Transports services are only available from 09:00AM until 05:00PM.' , @lang = 'us_english' , @with_log = 'FALSE' GO EXEC sp_addmessage @msgnum = 600001, @severity = 15, @msgtext = 'La hora %s indicada no es vlida. Los servicios nicamente estan disponibles desde las 9h hasta las 17h.' , @lang = 'Spanish' , @with_log = 'FALSE' GO

Severity level Importante pues determinar el comportamiento del sistema en base a la severidad del error. TABLA 1: RAISERROR Severity Categories Severity Range Error Number Info @@ERROR Logged As 1 hasta 9 In black NOT SET Informational 10 Not provided NOT SET Informational 11 hasta 14 In red SET Informational 15 In red SET Warning 16 In red SET Error State Los valores son de 1 a 127. Se sabe que cada mensaje tiene un estado determinado pero Microsoft no lo ha documentado. Un estado 127 significa que el cliente se ha desconectado sin embargo esa informacin es trivial puesto que una severidad superior a 18 implica el mismo comportamiento nosotros. Procedure En qu objeto (contenedor del T-SQL) se ha producido. Line La lnea en que se ha producido. Message text La descripcin del error o mensaje. Volvamos a la captura del error pero ahora utilizando RAISERROR:

BEGIN TRY SELECT 1/0 END TRY BEGIN CATCH ... -- Snippet de los BOL de SQL Server. DECLARE @ErrorMessage NVARCHAR(4000); DECLARE @ErrorSeverity INT; DECLARE @ErrorState INT; SELECT @ErrorMessage = ERROR_MESSAGE(), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); RAISERROR (@ErrorMessage, -- Message text. @ErrorSeverity, -- Severity. @ErrorState -- State. ); END CATCH

Este es un ejemplo de control de error no esperado mediante RAISERROR. La peculiaridad reside que en desconocemos la severidad del mismo. Segn la Tabal 1, si la severidad es inferior o igual a 10, desde la llamada cliente NO se producir ninguna Excepcion. Sin embargo si es superior s; ejemplo:
try { //lanzamos el SP res = dbCommand.ExecuteNonQuery(); } catch (SqlException sqlex) { //la severidad es superior a 10, luego entra aqu. } catch (Exception ex) { //otra excepcin no controlada a nivel de aplicacin. }

El problema est que ante un error de severidad leve (10), como por ejemplo, un error 718 producido por: 708 No hay suficiente espacio de direcciones virtuales en el servidor o no hay suficiente memoria virtual en el equipo. Se ha usado la memoria reservada %1! veces desde el inicio. Cancele la consulta y vuelva a ejecutarla, reduzca la carga del servidor o cancele otras aplicaciones. El SP se ejecutar correctamente sin embargo la nica forma de obtener ese mensaje desde ADO.NET es suscribindonos al evento InfoMessage del objeto DbConnection.
conexion.InfoMessageConnection += new System.Data.SqlClient.SqlInfoMessageEventHandler (conexion_InfoMessageConnection); void conexion_InfoMessageConnection(object sender, System.Data.SqlClient.SqlInfoMessageEventArgs e){ { //aqu obtenemos el mensaje string res = e.Message; }

Para los errores de severidad 19 o mayor se exige que: - En la llamada a RAISERROR se especifique la opcin WITH LOG. - Los autores pertenecen la funcin sysadmin. Un ejemplo: Esta sentencia no dar error pero no guardar LOG en el visor de sucesos.
RAISERROR('esto es una prueba',15,217)

Esta otra guardar una entrada en el visor de sucesos como Warning (TABLA 1)
RAISERROR('esto es una prueba',15,217) WITH LOG

Esta es idntica a las anteriores pero se procesa como Error no como Warning.
RAISERROR('esto es una prueba',16,217) RAISERROR('esto es una prueba',16,217) WITH LOG

La siguiente sentencia NO funcionar:


RAISERROR('esto es una prueba',19,217)

Sin embargo la siguiente si


RAISERROR('esto es una prueba',19,217) WITH LOG

Los resultados en el visor de sucesos: Error 08/05/2008 12:09:55 MSSQL$$$$$$$$$ 17063 (2) Advertencia 08/05/2008 12:05:46 MSSQL$$$$$$$$$ 17063 (2) Error 08/05/2008 12:05:12 MSSQL$$$$$$$$$ 17063 (2)

Das könnte Ihnen auch gefallen