none
Excepción no controlada del tipo 'System.Data.SqlClient.SqlException' en System.Data.dll // Información adicional: Error converting data type nvarchar to numeric RRS feed

  • Pregunta

  • buen dia 

    tengo el siguiente problema me salta el error pero no encuentro porque muestro el codigo:

                           

    string query = "update deptos

    set nombre_apellido = @nombre ,

    dni = @dni , domicilio = @domi

    cilio , profesion = @profesion , id_afiliado = @id , estado = @estado , acompaa = @a , dnia = @dnia , relaa = @relaa , acompab = @b , dnib = @dnib , relab = @relab , acompac = @c , dnic = @dnic , relac = @relac , acompad = @d , dnid = @dnid , relad = @relad where depto_numero = 1 and id_temporada = 1 ";
                string query2 = "insert into pagos (id_deptos,id_temporada,concepto1,monto,fecha_pago,nombre_afil,dni) values (@depto,@tempo,@concepto1,@montopago,@fecha,@nombrepago,@dnipago)";
                string query3 = "select seña from deptos where depto_numero = 1 and estado = 1 and id_temporada = 1";

                conexion.Open();
                SqlCommand comando = new SqlCommand(query, conexion);
                SqlCommand comando2 = new SqlCommand(query2, conexion);
                SqlCommand comando3 = new SqlCommand(query3, conexion);

                SqlDataReader registro = comando3.ExecuteReader();
                registro.Read();
                var seña = registro["seña"].ToString();
                int seña2 = Convert.ToInt32(seña);
                comando2.Parameters.AddWithValue("@depto", 1);
                comando2.Parameters.AddWithValue("@tempo", 1);
                comando2.Parameters.AddWithValue("@concepto1", "seña");
                comando2.Parameters.AddWithValue("@montopago",seña2);
                comando2.Parameters.AddWithValue("@nombrepago", textBox_nombre_apellido.Text);
                comando2.Parameters.AddWithValue("@fecha", DateTime.Today);                           
                comando2.Parameters.AddWithValue("@dnipago", textBox_dni.Text);

                comando.Parameters.AddWithValue("@nombre", textBox_nombre_apellido.Text);
                comando.Parameters.AddWithValue("@dni", textBox_dni.Text);
                comando.Parameters.AddWithValue("@domicilio", textBox_Domicilio.Text);
                comando.Parameters.AddWithValue("@profesion", textBox_Profesion.Text);
                comando.Parameters.AddWithValue("@id", textBox_afiliadoN.Text);
                comando.Parameters.AddWithValue("@estado",0);
                comando.Parameters.AddWithValue("@a", textBox_acompa_a.Text);
                comando.Parameters.AddWithValue("@dnia", textBox_acompa_a_dni.Text);
                comando.Parameters.AddWithValue("@relaa", textBox_relaa.Text);
                comando.Parameters.AddWithValue("@b", textBox_acompa_b.Text);
                comando.Parameters.AddWithValue("@dnib", textBox_acompa_b_dni.Text);
                comando.Parameters.AddWithValue("@relab", textBox_relab.Text);
                comando.Parameters.AddWithValue("@c", textBox_acompa_c.Text);
                comando.Parameters.AddWithValue("@dnic", textBox_acompa_c_dni.Text);
                comando.Parameters.AddWithValue("@relac", textBox_relac.Text);
                comando.Parameters.AddWithValue("@d", textBox_acompa_d.Text);
                comando.Parameters.AddWithValue("@dnid", textBox_acompa_d_dni.Text);
                comando.Parameters.AddWithValue("@relad", textBox_relad.Text);

                comando.ExecuteNonQuery(); el error me tira aca
                comando2.ExecuteNonQuery();

                conexion.Close();
                MessageBox.Show("Actualizado");

    muestro definicion de la tabla:

    CREATE TABLE [dbo].[deptos] (
        [id_deptos]       SMALLINT      IDENTITY (1, 1) NOT NULL,
        [montos]          NUMERIC (18)  NULL,
        [seña]            NUMERIC (18)  NULL,
        [saldo]           NUMERIC (18)  NULL,
        [id_temporada]    SMALLINT      NULL,
        [depto_numero]    SMALLINT      NULL,
        [fechas]          NCHAR (50)    NULL,
        [nombre_apellido] NVARCHAR (50) NULL,
        [dni]             NUMERIC (18)  NULL,
        [Domicilio]       NVARCHAR (50) NULL,
        [id_afiliado]     SMALLINT      NULL,
        [Estado]          SMALLINT      NULL,
        [sellado]         DECIMAL (18)  NULL,
        [profesion]       NVARCHAR (50) NULL,
        [temporada]       NVARCHAR (50) NULL,
        [acompaa]         NVARCHAR (50) NULL,
        [dnia]            NUMERIC (18)  NULL,
        [relaa]           NVARCHAR (50) NULL,
        [acompab]         NVARCHAR (50) NULL,
        [dnib]            NUMERIC (18)  NULL,
        [relab]           NVARCHAR (50) NULL,
        [acompac]         NVARCHAR (50) NULL,
        [dnic]            NUMERIC (18)  NULL,
        [relac]           NVARCHAR (50) NULL,
        [acompad]         NVARCHAR (50) NULL,
        [dnid]            NUMERIC (18)  NULL,
        [relad]           NVARCHAR (50) NULL,
        CONSTRAINT [PK_deptos] PRIMARY KEY CLUSTERED ([id_deptos] ASC)

    GRacias espero me puedan ayudar

    viernes, 25 de octubre de 2019 14:27

Respuestas

  • Fíjate que en la tabla hay varios datos que son de tipo numérico, pero que en la llamada que haces estás pasándolos todos como nvarchar. Esto sucede porque usas AddWithValue y en el Value metes el .Text de un textbox. Como el .Text es una propiedad de tipo String, el AddWithValue genera un parámetro de tipo NVarchar.

    Entonces, cuando el servidor SQL recibe ese parámetro de tipo nvarchar y se encuentra con que tiene que almacenarlo en un campo numérico, aplica una conversión implícita de nvarchar a número. Si resulta que el texto que hay dentro del varchar no tiene un formato que SQL reconozca como numérico, pues entonces sale ese error que estás viendo (Error converting data type nvarchar to numeric).

    ¿Qué valores de texto pueden dar esté error? Aparte de los "evidentes" (por ejemplo, si en el textbox pone "Pepe" está claro que eso no es un número) un posible error es que el textbox esté vacío (el texto vacío no se convierte en cero, sino que da un error). Y otro error es que haya una coma decimal (SQL siempre necesita punto en lugar de coma), o que haya espacios en blanco, o puntos de miles, etc.

    ¿Cuál es la solución buena? No le pases el .Text directamente al AddWithValue. Usa una de las instrucciones de conversión (por ejemplo, TryParse) para convertir el .Text a una variable de tipo Decimal, y entonces pasa ese decimal (¡numérico, no lo vuelvas a convertir a texto!) al AddWithValue.

    Desde luego, si el textbox tiene algún valor no numérico, la conversión del TryParse fallará, pero la puedes controlar con un "if" y mostrar el problema al usuario.

    viernes, 25 de octubre de 2019 14:55
    Moderador
  • No. De esa manera todavía puede fallar. Si el problema es que el textBox_afiliadoN.Text contiene algo que el sistema no reconoce como un número válido, pues entonces dará un error al intentar meterlo en un dato numérico. Da igual que la conversión de texto a número se haga en el momento de pasar el parámetro a la UPDATE o en el momento de pasar el texto al parámetro. Si el texto no vale, no vale. Hay que controlarlo antes.

    Una posible forma de controlar el valor es esta:

    int afiliadoN;
    bool ok = int.TryParse(textBox_afiliadoN.Text, out afiliadoN);
    if (!ok)
    {
        throw new Exception(string.Format("¡Que no! No puedes grabar '{0}' porque no lo reconocemos como número", textBox_afiliadoN.Text));
    }
    
    comando.Parameters.Add("@id", SqlDbType.Int);
    comando.Parameters["@id"].Value = afiliadoN;

    Por supuesto, si el Text no contiene un número, se meterá por el "if" y dará el error que he puesto ahí. Obviamente, solo es un ejemplo; en lugar de ese "throw" ahí escribirás lo que sea necesario para informar al usuario que ha tecleado un valor incorrecto.

    viernes, 25 de octubre de 2019 18:28
    Moderador
  • Gracias por responder podria solucionar el problema pasando

      comando.Parameters.Add("@id", SqlDbType.Int);
                comando.Parameters["@id"].Value = textBox_afiliadoN.Text;


    viernes, 25 de octubre de 2019 16:03
  • No, eso no es motivo suficiente para que falle. Es perfectamente legítimo abrir una sola vez la conexión y ejecutar varios commands sobre ella. Más bien tiene pinta de que cuando estaban todos juntos se mezclaba algo y se asignaba alguno de los parámetros indebidamente. Al reorganizar el código para ejecutarlos por separado, seguramente ocurrió la coincidencia de que se arregló el parámetro que estaba mal. Pero si se ponen todos correctamente en cada uno de los command correctos y con los valores correctos, es perfectamente viable el ejecutarlos todos sobre la misma conexión sin necesidad de cerrarla entre medias. Esto por sí solo no tiene por qué provocar ningún error.
    sábado, 26 de octubre de 2019 15:34
    Moderador

Todas las respuestas

  • Fíjate que en la tabla hay varios datos que son de tipo numérico, pero que en la llamada que haces estás pasándolos todos como nvarchar. Esto sucede porque usas AddWithValue y en el Value metes el .Text de un textbox. Como el .Text es una propiedad de tipo String, el AddWithValue genera un parámetro de tipo NVarchar.

    Entonces, cuando el servidor SQL recibe ese parámetro de tipo nvarchar y se encuentra con que tiene que almacenarlo en un campo numérico, aplica una conversión implícita de nvarchar a número. Si resulta que el texto que hay dentro del varchar no tiene un formato que SQL reconozca como numérico, pues entonces sale ese error que estás viendo (Error converting data type nvarchar to numeric).

    ¿Qué valores de texto pueden dar esté error? Aparte de los "evidentes" (por ejemplo, si en el textbox pone "Pepe" está claro que eso no es un número) un posible error es que el textbox esté vacío (el texto vacío no se convierte en cero, sino que da un error). Y otro error es que haya una coma decimal (SQL siempre necesita punto en lugar de coma), o que haya espacios en blanco, o puntos de miles, etc.

    ¿Cuál es la solución buena? No le pases el .Text directamente al AddWithValue. Usa una de las instrucciones de conversión (por ejemplo, TryParse) para convertir el .Text a una variable de tipo Decimal, y entonces pasa ese decimal (¡numérico, no lo vuelvas a convertir a texto!) al AddWithValue.

    Desde luego, si el textbox tiene algún valor no numérico, la conversión del TryParse fallará, pero la puedes controlar con un "if" y mostrar el problema al usuario.

    viernes, 25 de octubre de 2019 14:55
    Moderador
  • Gracias por responder podria solucionar el problema pasando

      comando.Parameters.Add("@id", SqlDbType.Int);
                comando.Parameters["@id"].Value = textBox_afiliadoN.Text;


    viernes, 25 de octubre de 2019 16:03
  • No. De esa manera todavía puede fallar. Si el problema es que el textBox_afiliadoN.Text contiene algo que el sistema no reconoce como un número válido, pues entonces dará un error al intentar meterlo en un dato numérico. Da igual que la conversión de texto a número se haga en el momento de pasar el parámetro a la UPDATE o en el momento de pasar el texto al parámetro. Si el texto no vale, no vale. Hay que controlarlo antes.

    Una posible forma de controlar el valor es esta:

    int afiliadoN;
    bool ok = int.TryParse(textBox_afiliadoN.Text, out afiliadoN);
    if (!ok)
    {
        throw new Exception(string.Format("¡Que no! No puedes grabar '{0}' porque no lo reconocemos como número", textBox_afiliadoN.Text));
    }
    
    comando.Parameters.Add("@id", SqlDbType.Int);
    comando.Parameters["@id"].Value = afiliadoN;

    Por supuesto, si el Text no contiene un número, se meterá por el "if" y dará el error que he puesto ahí. Obviamente, solo es un ejemplo; en lugar de ese "throw" ahí escribirás lo que sea necesario para informar al usuario que ha tecleado un valor incorrecto.

    viernes, 25 de octubre de 2019 18:28
    Moderador
  • muchas gracias por la respuesta, me ayudo perfecto esa excepción, pero el error me desapareció cuando deje de utilizar los tres command simultáneamente, trabaje individualmente abría y cerraba la conexión por cada command y no me aparecieron mas los errores.

    gracias por su tiempo


    jose horacio villamayor

    sábado, 26 de octubre de 2019 14:48
  • No, eso no es motivo suficiente para que falle. Es perfectamente legítimo abrir una sola vez la conexión y ejecutar varios commands sobre ella. Más bien tiene pinta de que cuando estaban todos juntos se mezclaba algo y se asignaba alguno de los parámetros indebidamente. Al reorganizar el código para ejecutarlos por separado, seguramente ocurrió la coincidencia de que se arregló el parámetro que estaba mal. Pero si se ponen todos correctamente en cada uno de los command correctos y con los valores correctos, es perfectamente viable el ejecutarlos todos sobre la misma conexión sin necesidad de cerrarla entre medias. Esto por sí solo no tiene por qué provocar ningún error.
    sábado, 26 de octubre de 2019 15:34
    Moderador