none
Valor Nulo en consulta select

    Pregunta

  • Hola a todos:

    Tengo un error en la consulta siguiente que lee dos campos booleanos, los cuales están a "False" (0), pero resulta que el catch me arroja la siguiente excepción: La columna del valor especificado (1) contiene el valor DBNull que no se puede representar como un tipo del sistema .NET integrado. Use SQLTypes o la propiedad IsDbnull.

    No entiendo la razón del mensaje o como solucionarlo, ya que si paso un breakpoint por los valores del datareader me está dando los valores de los dos como "false".

    Os pongo la consulta:

    Public Shared Sub CargaValorPropiedadesInicioFlujosDescontados()
            Try
    
                Dim da As DataAccessInvariant = DataAccessInvariant.GetDataAccessInvariant(Configuracion.CadenaConexion)
    
                ' Declaramos una variable Connection
                Using cnn As DbConnection = da.CreateConnection()
    
                    ' Creamos el Commando
                    Dim cmd As DbCommand = cnn.CreateCommand()
    
                    cmd.CommandText = "SELECT ValoresInicioACero, IncrementoAutomaticoReal FROM Valoraciones WHERE Cod_Empresa = @empresa"
    
                    With cmd.Parameters
                        .Clear()
                        .Add(Configuracion.CreateParameter(cmd, "@empresa", VarGlobal.StrCodEmpresa))
                    End With
    
                    ' Asignamos la conexión al comando
                    cmd.Connection = cnn
                    cnn.Open()
    
                    Using dr As DbDataReader = cmd.ExecuteReader()
                        While dr.Read
                            bolValoresInicioACero = dr.GetBoolean(0)
                            bolIncremAutomaticoReal = dr.GetBoolean(1)
                        End While
                    End Using
                End Using
    
            Catch ex As Exception
                MessageBox.Show("Bloqueo en carga de Fórmula: '3512'" & vbCrLf & ex.Message & vbCrLf &
                   "Acepte para continuar.", "FINANCIAL SYSTEM", MessageBoxButtons.OK, MessageBoxIcon.Error)
    
            End Try
        End Sub

    Muchas gracias.

    Gemma


    miércoles, 16 de noviembre de 2016 16:37

Respuestas

  • "gemma_campillo" escribió:

    > Tengo un error en la consulta siguiente que lee dos campos booleanos, los cuales
    > están a "False" (0), pero resulta que el catch me arroja la siguiente excepción:
    > La columna del valor especificado (1) contiene el valor DBNull que no se puede
    > representar como un tipo del sistema .NET integrado. Use SQLTypes o la propiedad
    > IsDbnull.

    Si de verdad estuvieran a "False" (0) los valores de esos campos, no obtendrías el error que estás teniendo, pero me parece a mí que esos campos tienen un valor NULL tan grande como una catedral, lo que quiere decir que no tienen ningún valor: ni "False", ni "True", ni "Esto" ni tampoco "Aquello". Tienen el valor NULL, o si lo prefieres, el valor DBNull.

    El propio mensaje de error te está diciendo que utilices el método (no la propiedad) IsDBNull del objeto DataReader para conocer si en verdad el campo tiene un valor válido, entendiendo por valor válido todo aquel valor que no sea NULL, que en el caso de una columna del tipo Boolean (Sí/No o bit), los únicos valores serán True, False o NULL, en éste último caso, si has indicado que el campo admita valores NULL, claro está.

    Ejecuta el bloque Using ... End Using del objeto DbDataReader como indico a continuación:

        Using dr As DbDataReader = cmd.ExecuteReader()
    
            If (dr.HasRows) Then
                ' Existe al menos una fila. Procedemos a leer
                ' los valores de sus columnas.
                dr.Read()
    
                If (Not dr.IsDBNull(0)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolValoresInicioACero = dr.GetBoolean(0)
                End If
    
                If (Not dr.IsDBNull(1)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolIncremAutomaticoReal = dr.GetBoolean(1)
                End If
    
            End If
    
        End Using
    

    Obviamente, si algún campo tiene el valor NULL, la variable bolValoresInicioACero o bolIncremAutomaticoReal tendrán el valor False.

    Observa la consulta SQL de selección que estás ejecutando:

        cmd.CommandText = "SELECT ValoresInicioACero, IncrementoAutomaticoReal " & _
                          "FROM Valoraciones WHERE Cod_Empresa = @empresa"

    Que yo sepa, esa consulta solamente puede devolver una sola fila o ninguna, en el supuesto de que no exista ningún registro donde el valor del campo Cod_Empresa coincida con el valor del parámetro especificado. Pues si solamente puede devolver o una o ninguna fila, ¿para qué ejecutas la instrucción While ... End While?

         While dr.Read
             bolValoresInicioACero = dr.GetBoolean(0)
             bolIncremAutomaticoReal = dr.GetBoolean(1)
         End While

    Eso estaría bien cuando el lector de datos contiene más de una fila. ;-)

    >  ' Creamos el Commando
    >  Dim cmd As DbCommand = cnn.CreateCommand()
    >
    >  cmd.CommandText = ...
    >
    >  With cmd.Parameters
    >      .Clear()
    >      .Add(Configuracion.CreateParameter(cmd, "@empresa", VarGlobal.StrCodEmpresa))
    >  End With

    Si creas un nuevo objeto DbCommand, se comprende que su colección Parameters está demasiado "limpia" para que tenga algún parámetro, por tanto, ¿por qué llamas al método Clear de la colección Parameters? ¡Ay, ay! ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    miércoles, 16 de noviembre de 2016 18:44
    Moderador
  • "gemma_campillo" escribió:

    > Exactamente el dr.Hasrow lo que hace es ver que en el
    > datareader hay filas existentes, no?

    Efectivamente. Dicha propiedad nos indica si el lector de datos abierto mediante el método ExecuteReader contiene al menos una fila (True) o no (False).

    > Me tira un error: SQLServer Compact no admite llamadas a la
    > propiedad HasRows si no se puede desplazar el cursor subyacente.
    >
    > La he puesto exactamente como me la has enseñado.

    Pero para que funcione la propiedad HasRows, el proveedor de datos subyacente la debe de implementar, y parece ser que el proveedor de datos .NET para SQL Server Compact no la admite, por tanto, no te va a quedar más remedio que continuar consultando el valor devuelto por el método Read del lector de datos, tal cual estabas haciendo, aunque la consulta SQL de selección te devuelva una única fila:

        Using dr As DbDataReader = cmd.ExecuteReader()
    
            While dr.Read()
    
                If (Not dr.IsDBNull(0)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolValoresInicioACero = dr.GetBoolean(0)
                End If
    
                If (Not dr.IsDBNull(1)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolIncremAutomaticoReal = dr.GetBoolean(1)
                End If
    
            End While
    
        End Using
    

    > Observa la consulta SQL de selección que estás ejecutando:
    >
    >    cmd.CommandText = "SELECT ValoresInicioACero, IncrementoAutomaticoReal " & _
    >                      "FROM Valoraciones WHERE Cod_Empresa = @empresa"
    >
    > Que yo sepa, esa consulta solamente puede devolver una sola fila o ninguna, en
    > el supuesto de que no > exista ningún registro donde el valor del campo
    > Cod_Empresa coincida con el valor del parámetro especificado. Pues si solamente
    > puede devolver o una o ninguna fila, ¿para qué ejecutas la instrucción
    > While ... End While?

    Quisiera puntualizar mi comentario anterior. Si el campo Cod_Empresa es la clave principal de la tabla Valoraciones, o sin ser la clave principal de la tabla no admite valores duplicados, está claro que esa consulta de selección solamente va a devolver una fila o ninguna. Pero si el campo admite valores duplicados, entonces sí puede devolver más de una fila, aunque en éste caso dicho campo no puede ser la clave principal de la tabla.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta gemma_campillo jueves, 17 de noviembre de 2016 8:45
    jueves, 17 de noviembre de 2016 7:34
    Moderador

Todas las respuestas

  • "gemma_campillo" escribió:

    > Tengo un error en la consulta siguiente que lee dos campos booleanos, los cuales
    > están a "False" (0), pero resulta que el catch me arroja la siguiente excepción:
    > La columna del valor especificado (1) contiene el valor DBNull que no se puede
    > representar como un tipo del sistema .NET integrado. Use SQLTypes o la propiedad
    > IsDbnull.

    Si de verdad estuvieran a "False" (0) los valores de esos campos, no obtendrías el error que estás teniendo, pero me parece a mí que esos campos tienen un valor NULL tan grande como una catedral, lo que quiere decir que no tienen ningún valor: ni "False", ni "True", ni "Esto" ni tampoco "Aquello". Tienen el valor NULL, o si lo prefieres, el valor DBNull.

    El propio mensaje de error te está diciendo que utilices el método (no la propiedad) IsDBNull del objeto DataReader para conocer si en verdad el campo tiene un valor válido, entendiendo por valor válido todo aquel valor que no sea NULL, que en el caso de una columna del tipo Boolean (Sí/No o bit), los únicos valores serán True, False o NULL, en éste último caso, si has indicado que el campo admita valores NULL, claro está.

    Ejecuta el bloque Using ... End Using del objeto DbDataReader como indico a continuación:

        Using dr As DbDataReader = cmd.ExecuteReader()
    
            If (dr.HasRows) Then
                ' Existe al menos una fila. Procedemos a leer
                ' los valores de sus columnas.
                dr.Read()
    
                If (Not dr.IsDBNull(0)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolValoresInicioACero = dr.GetBoolean(0)
                End If
    
                If (Not dr.IsDBNull(1)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolIncremAutomaticoReal = dr.GetBoolean(1)
                End If
    
            End If
    
        End Using
    

    Obviamente, si algún campo tiene el valor NULL, la variable bolValoresInicioACero o bolIncremAutomaticoReal tendrán el valor False.

    Observa la consulta SQL de selección que estás ejecutando:

        cmd.CommandText = "SELECT ValoresInicioACero, IncrementoAutomaticoReal " & _
                          "FROM Valoraciones WHERE Cod_Empresa = @empresa"

    Que yo sepa, esa consulta solamente puede devolver una sola fila o ninguna, en el supuesto de que no exista ningún registro donde el valor del campo Cod_Empresa coincida con el valor del parámetro especificado. Pues si solamente puede devolver o una o ninguna fila, ¿para qué ejecutas la instrucción While ... End While?

         While dr.Read
             bolValoresInicioACero = dr.GetBoolean(0)
             bolIncremAutomaticoReal = dr.GetBoolean(1)
         End While

    Eso estaría bien cuando el lector de datos contiene más de una fila. ;-)

    >  ' Creamos el Commando
    >  Dim cmd As DbCommand = cnn.CreateCommand()
    >
    >  cmd.CommandText = ...
    >
    >  With cmd.Parameters
    >      .Clear()
    >      .Add(Configuracion.CreateParameter(cmd, "@empresa", VarGlobal.StrCodEmpresa))
    >  End With

    Si creas un nuevo objeto DbCommand, se comprende que su colección Parameters está demasiado "limpia" para que tenga algún parámetro, por tanto, ¿por qué llamas al método Clear de la colección Parameters? ¡Ay, ay! ;-)


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    miércoles, 16 de noviembre de 2016 18:44
    Moderador
  • Hola maestro:

    Ay, ay ,ay. Llevas razón en todo jodidamente como siempre.

    Bueno, necesitaba tener claro el tratamiento en el reader de los valor nulos, ahora está muy claro.

    Lo del clear ya me dijiste que no es necesario y lo iré cambiando en la consultas que aún me quedan por revisar.

    Es una mala costumbre que arrastro de cuando creaba un New.Command con el OleDb.

    Enrique me queda la duda, la esto: If (dr.HasRows) Then

    Exactamente el dr.Hasrow lo que hace es ver que en el datareader hay filas existentes, no?.

    Bueno, querido amigo gracias como siempre. La duda de los DBNull la tenía aprendida a medias, ahora queda mucho más.

    Querido Enrique, un fuerte abrazo maestro.

    Gemma

               

    miércoles, 16 de noviembre de 2016 19:17
  • Hola maestro:

    Me tira un error: SQLServer Compact no admite llamadas a la propiedad HasRows si no se puede desplazar el cursor subyacente.

    La he puesto exactamente como me la has enseñado.

    Bueno, un abrazo.

    Gemma


    • Editado gemma_campillo miércoles, 16 de noviembre de 2016 20:57 sintaxis
    miércoles, 16 de noviembre de 2016 19:42
  • "gemma_campillo" escribió:

    > Exactamente el dr.Hasrow lo que hace es ver que en el
    > datareader hay filas existentes, no?

    Efectivamente. Dicha propiedad nos indica si el lector de datos abierto mediante el método ExecuteReader contiene al menos una fila (True) o no (False).

    > Me tira un error: SQLServer Compact no admite llamadas a la
    > propiedad HasRows si no se puede desplazar el cursor subyacente.
    >
    > La he puesto exactamente como me la has enseñado.

    Pero para que funcione la propiedad HasRows, el proveedor de datos subyacente la debe de implementar, y parece ser que el proveedor de datos .NET para SQL Server Compact no la admite, por tanto, no te va a quedar más remedio que continuar consultando el valor devuelto por el método Read del lector de datos, tal cual estabas haciendo, aunque la consulta SQL de selección te devuelva una única fila:

        Using dr As DbDataReader = cmd.ExecuteReader()
    
            While dr.Read()
    
                If (Not dr.IsDBNull(0)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolValoresInicioACero = dr.GetBoolean(0)
                End If
    
                If (Not dr.IsDBNull(1)) Then
                    ' Si el valor del campo NO ES DBNull, leemos su valor
                    bolIncremAutomaticoReal = dr.GetBoolean(1)
                End If
    
            End While
    
        End Using
    

    > Observa la consulta SQL de selección que estás ejecutando:
    >
    >    cmd.CommandText = "SELECT ValoresInicioACero, IncrementoAutomaticoReal " & _
    >                      "FROM Valoraciones WHERE Cod_Empresa = @empresa"
    >
    > Que yo sepa, esa consulta solamente puede devolver una sola fila o ninguna, en
    > el supuesto de que no > exista ningún registro donde el valor del campo
    > Cod_Empresa coincida con el valor del parámetro especificado. Pues si solamente
    > puede devolver o una o ninguna fila, ¿para qué ejecutas la instrucción
    > While ... End While?

    Quisiera puntualizar mi comentario anterior. Si el campo Cod_Empresa es la clave principal de la tabla Valoraciones, o sin ser la clave principal de la tabla no admite valores duplicados, está claro que esa consulta de selección solamente va a devolver una fila o ninguna. Pero si el campo admite valores duplicados, entonces sí puede devolver más de una fila, aunque en éste caso dicho campo no puede ser la clave principal de la tabla.


    Enrique Martínez Montejo
    [MS MVP - Visual Studio y Tecnologías de Desarrollo]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, se inteligente y activa la instrucción
    Option Strict.

    • Marcado como respuesta gemma_campillo jueves, 17 de noviembre de 2016 8:45
    jueves, 17 de noviembre de 2016 7:34
    Moderador
  • Hola maestro:

    Estuve mirando la propiedad HastRows y efectivamente no funciona en sqlCompact, lo que hice ayer por la noche es lo que me acabas de explicar, la quité y la dejé como tu has indicado y funciona perfectamente. Por otro lado esa consulta nada más tiene una fila. Todo perfecto.

    Maestro querido muchas gracias como siempre de la Ay, Ay, Ay....

    Un abrazo.

    Gemma

    jueves, 17 de noviembre de 2016 8:45