SqlException
Manejo de excepciones especializadas.

Fecha: 02/Feb/2005 (1 Febrero 2005)
Autor:
Misael Monterroca, [email protected]

 


 

Una ventaja del manejo de excepciones es el poder manejar excepciones especializadas o personalizadas, con lo cual, podemos realizar un mejor manejo en el flujo de nuestra aplicaci�n al poder reaccionar ante un error especifico y de �sta manera realizar acciones especificas.

Como ejemplo, utilizaremos la excepci�n SqlException, mediante la cual, podemos recuperar los c�digos de error que Sql Server genera internamente, �stos errores van desde un "Acceso denegado al usuario x" o "Nombre de objeto invalido x" por poner un ejemplo.

SqlException nos expone  a trav�s de su propiedad SqlException.Errors una colecci�n que contiene uno o m�s objetos del tipo SqlError, con los cuales, podremos conocer el error exacto que ocurrio en el servidor, utilizando �sta informaci�n construiremos una aplicaci�n a manera de ejemplo, mediante la cual controlaremos los errores basicos que suceden al momentos de realizar la conexi�n hacia la base de datos.

La aplicaci�n nos pedira los siguientes datos, mediante los cuales esperaremos una determinada excepci�n de sql.

Comunmente dentro del manejo de errores unicamenye incluimos el manejador de la excepci�n "general" Exception ,pero en esta ocasi�n dentro de nuestro bloque Try, incluiremos una excepci�n m�s SqlException .

try
{
    //hacer algo
}
catch (SqlException
ex)
{
//hacer algo  

}
catch(Exception ex)
{
//hacer algo
}

A�n cuando la �nica excepci�n que intentamos utilizar ser� SqlException, es recomendable dejar el manejador de las excepciones generales, ya que no siempre (dependiendo de la implementaci�n del bloque try) las exepciones internas ser�n propiciadas por Sql, aunque insisto, eso depende por mucho de la implementaci�n que se tenga.

Si unicamente intentaramos detectar la ejecuci�n a manera general, bastaria con obtener el mensaje de error que genero Sql Server SqlException.Message, para este ejemplo entraremos un poco m�s en detalle y obtendremos el error detallado generado en el servidor, para �sto, tendremos que realizar un for dentro de nuestro bloque Catch para asi obtener todos los errores generados.

catch (SqlException ex)
{
    foreach (SqlError sError in ex.Errors)
    {
        //Implementaci�n.....

La clase que realmente contiene la informaci�n detallada del error generado es SqlError, para obtener el c�digo de error generado utilizaremos la propiedad number SqlError.Number, �ste c�digo de error es que el Sql Server genero internamente, para ver todos los c�digos de error posibles consulte la documentaci�n de Sql Server. Si bien, en este ejemplo nos limitamos a reemplazar el mensaje de error generado por uno m�s especifico para el usuario, esta no es la �nica utilidad que podemos obtener, por ejemplo, en caso de que el usuario y password sean incorrectos, podriamos guardar una bitacora con el usuario que esta intentando acceder a nuestra base de datos.

Por ejemplo, si intentaramos acceder a un servidor y �ste no fuera encontrado se generaria un Error 17, estos errores los capturaremos dentro de nuestro bloque switch

      switch (sError.Number)
                    {
                        case 17:
                        MessageBox.Show("El servidor '" + servidor  + "' no existe, por favor verifique el nombre");
                        break ;

 

Si el usuario y password fueran incorrectos, el error generado seria el numero 18456, hay que tener especial antenci�n en el caso de que se generen m�s de 1 error, tal es el caso de un usuario el cual este tratando de acceder a una base de datos en la cual no tiene permisos, para �ste escenario primero se generaria un error 4060, el cual pertenece a //Cannot open database requested in login '%.*ls'. Login fails. pero tambien se generara un error 18456 //Login failed for user '%ls'. ya que efectivamente, el acceso fallo, para este caso se pueden tener dos posibles acciones, informar de un error y salir del bucle, o informar de ambos errores.

Por ultimo, la clase SqlError nos provee de varia informaci�n, la cual nos puede llegar a ser �til, para el caso del error 208 //Invalid object name '%ls'." Nombre de objeto invalido, este error podria darse por ejemplo, dentro de una vista, pero para tener una mayor referencia el objeto SqlError, nos da la informaci�n de la linea en la cual ocurrio el error SqlError.LineNumber, al final de cuentas SqlError nos provee de la misma informaci�n que si ocurria un error al ejecutar una sentencia desde el Analizador de Consultas.

Servidor: mensaje 208, nivel 16, estado 1, l�nea 1 El nombre de objeto 'sysobject' no es v�lido.

using System;
using System.Data.SqlClient;
using System.Windows.Forms;

namespace ExcepcionesSql
{
    /// <summary>
    /// Summary description for DB.
    /// </summary>
    public class DB
    {
        /// <summary>
        /// Realiza la conexi�n a un servidor Sql Server e intenta ejecutar un determinado comando.
        /// </summary>
        /// <param name="servidor">Nombre del servidor</param>
        /// <param name="usuario">Nombre de usuario</param>
        /// <param name="clave">Password del usuario</param>
        /// <param name="basedatos">Base de datos en el servidor sql</param>
        /// <param name="sqlText">Un comando Sql (Select)</param>
        public DB(string servidor,string usuario,string clave,string basedatos,string sqlText)
        {
            // Se crea la variable que contiene el string de conexi�n
            string adoCon = String.Format("Data Source={0};Initial Catalog={1};User Id={2};Password={3}",servidor,basedatos,usuario,clave);

            try
            {   
                using (SqlConnection sCon = new SqlConnection(adoCon))
                {
                    sCon.Open();   
                    MessageBox.Show("Se realizo la conexi�n");
                    SqlCommand sComando = new SqlCommand(sqlText,sCon);
                    sComando.ExecuteNonQuery();//SOlo para comprobar que la sentencia puede ejecutarse.
                    MessageBox.Show("Se realizo la consulta");
                }


            }
            catch (SqlException ex)
            {

                foreach (SqlError sError in ex.Errors)
                {

                    switch (sError.Number)
                    {
                        case 17:
                        MessageBox.Show("El servidor '" + servidor  + "' no existe, por favor verifique el nombre");
                        break;
                        case 18452:    //Login failed for user '%ls'. Reason: Not associated with a trusted SQL Server connection.
                        MessageBox.Show("Especifique un usuario y password");
                        break;
                        case 18456: //Login failed for user '%ls'.
                        MessageBox.Show("El usuario o password es incorrecto");
                        break;   
                        case 4060:    //Cannot open database requested in login '%.*ls'. Login fails.
                        MessageBox.Show("El usuario no tiene permisos para acceder a la base de datos '" + basedatos + "'");
                        break;   
                        case 208:    //Invalid object name '%ls'."
                        MessageBox.Show("El nombre del objeto es incorrecto, para mayor informaci�n consulte la lnea :" + sError.LineNumber);
                        break;
                        default:
                        MessageBox.Show(sError.Message);
                        break;
                    }


                }
            }
            catch(Exception ex)
            {   
                MessageBox.Show(ex.Message);
            }

        }
    }
}


Espacios de nombres usados en el c�digo de este art�culo:

System.Data.SqlClient

 


ir al ndice

Fichero con el c�digo de ejemplo: neo_mx_SqlException.zip - 20.3 KB