Actualmente estoy utilizando sql lector de datos (en vb.net) para el extracto de un artículo objeto a través de un procedimiento almacenado de SQL Server 2008 de la base de datos. La parte de este objeto incluye las dos propiedades que se muestran a continuación:

theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness"))))
theArticle.Relevance = ((myReader.GetInt32(myReader.GetOrdinal("Relevance"))))

Mi problema es que la Veracidad y la Relevancia puede devolver un valor null y esto está causando la función a caer.

Creo que entiendo por qué. Estoy pidiendo un valor entero (getin32) y porque se devuelve null falla.

¿Cómo puedo acomodar el valor nulo de la base de datos para que no se caiga?

OriginalEl autor Cunners | 2009-10-03

7 Comentarios

  1. 16

    Usted puede comprobar si es o no una determinada posición ordinal es el uso de null .IsDBNull() y, a continuación, hacer algo – por ejemplo, fijar su valor a -1 o algo:

    int myOrdinal = myReader.GetOrdinal("Truthfullness");
    
    if(myReader.IsDBNull(myOrdinal))
    {
      theArticle.Truthfulness = -1;
    }
    else
    {
      theArticle.Truthfulness = myReader.GetInt32(myOrdinal);
    }

    Como Mike Hofer señala en su respuesta, también se puede envolver toda esta lógica en un método de extensión:

    public static class SqlDataReaderExtensions 
    {
        public static int SafeGetInt32(this SqlDataReader reader, 
                                       string columnName, int defaultValue) 
        {
            int ordinal = reader.GetOrdinal(columnName);
    
            if(!reader.IsDbNull(ordinal))
            {
               return reader.GetInt32(ordinal);
            } 
            else
            {
               return defaultValue;
            }
        }
    }

    y, a continuación, sólo tiene que utilizar esa «SafeGetInt32» método:

      theArticle.Truthfulness = myReader.SafeGetInt32("Truthfullness", -1);

    Marc

    o capturar la excepción y tratar con él
    Sí, podría hacer que también -, sino evitar una excepción es mejor que la captura y manejo de uno (en general)
    con tu comentario en mi respuesta. Eliminarlo. Gracias por dejar claro. Su comentario fue: «yo no tiink esto va a funcionar, ya que si la base de datos de la columna es NULL, el .GetInt32() la llamada se producirá una excepción – no vas a volver un valor NULL, que luego podrá alimentar a la «??» operador de….»
    Hoy en día probablemente sería volver acepta valores null int: stackoverflow.com/a/53391141/572644

    OriginalEl autor marc_s

  2. 2

    Hizo de verificación, SqlDataReader.IsDBNull Método? Probablemente algo como:

    if(myReader.IsDBNull(myReader.GetOrdinal("Truthfulness"))
    theArticle.Truthfulness = string.Empty;
    else
    theArticle.Truthfulness = ((myReader.GetInt32(myReader.GetOrdinal("Truthfulness"))))
    así, la cadena de caracteres.Vacía no sirve de mucho si usted está tratando con un int32 propiedad……

    OriginalEl autor KMån

  3. 1

    Usted sabe, estoy de acuerdo con esto todo el tiempo en Oracle. Para limpiar el código, me escribió un conjunto de métodos de extensión para simplificar la operación:

    using System.Data.OracleClient;
    public static class OracleDataReaderExtensions 
    {
        public static int GetInt32(this OracleDataReader reader, string columnName, int defaultValue) 
        {
            return reader.GetInt32(reader.GetOrdinal(columnName)) != DbNull.Value ? 
                   reader.GetInt32(reader.GetOrdinal(columnName)) : 
                   defaultValue;
        }
    }

    Crear una sobrecarga para cada tipo que desea devolver. Yo trabajo principalmente con string, int, fecha y decimal. Recuerde YAGNI (no es necesario trabajar con cada tipo que sea compatible con el lector, sólo aquellos que realmente usa.)

    Una extensión de la clase como esta para SQL Server es realmente fácil de escribir, y se simplifican ENORMEMENTE su trabajo. Confía en mí en esto. Iba a mentir a usted? 🙂

    No creo que esto va a funcionar, ya que si la columna en la base de datos es NULO, entonces la llamada a GetInt32() hará una excepción. No se puede comparar que GetInt32() la llamada contra DBNull.Valor y de reaccionar a eso….
    En realidad, funciona. Yo lo uso todos los días.
    La razón por la que funciona es porque estamos usando el cortocircuito ?: operador. Si no es null, se devuelven. De lo contrario, se devuelve el valor predeterminado.
    en realidad, al menos con SQL Server, no NO trabajo – GetInt32() producirá una excepción si el subyacente db columna contiene NULL, y no se puede comparar la GetInt32() llamada a DBNull.Valor VS2008 se quejan y ni siquiera compilarlo.
    Pero definitivamente me gusta la idea de envolver en un método de extensión – hace la vida mucho más fácil!

    OriginalEl autor Mike Hofer

  4. 1

    Esta versión genérica puede ser de uso:

        private T ValueOrDefault<T>(System.Data.IDataReader rdr, string columnName)
        {
            T vod = default(T);
            try
            {
                int idx = rdr.GetOrdinal(columnName);
                if (!rdr.IsDBNull(idx))
                    return (T)rdr[idx];
            }
            catch (IndexOutOfRangeException) { }
    
            return vod;
        }

    Podría extenderse a coger InvalidCastException, o el uso Convertir.ChangeType en lugar de casting?

    Me gusta esta opción, excepto para el IndexOutOfRangeException instrucción catch. Yo creo que te gustaría saber tan pronto como sea posible si el esquema de la estructura ha cambiado en lugar de empujar a los valores predeterminados a otras partes de su sistema.

    OriginalEl autor cyberenergy

  5. 0

    IsDbNull(int) suele ser mucho más lento que el uso de métodos como GetSqlInt32 y, a continuación, comparar a DBNull.Valor o usando el propio .IsNull Como:

        public static int Int32(this SqlDataReader r, int ord)
        {
            var t = r.GetSqlInt32(ord);
            return t.IsNull ? default(int) : t.Value;
        }

    Intentado un par de plantilla de soluciones, pero sin éxito hasta el momento. El problema es que todos Sql-tipos (SqlInt32 aquí) los tipos son en realidad estructuras y a pesar de que todos tenemos .Valor de la propiedad C# no tiene real plantillas para manejar eso. También ellos tienen su propia INullable interfaz que tiene sólo .IsNull y no es conpatible con Nyllable<>.

    Sospecho que uno necesitaría conjunto completo de Sql-tipos como C# o plantillas para agregar ICOnvertible a ellos con el fin de ser capaz de tener sólo uno o dos de plantilla métodos.

    Si alguien tiene quizá una idea con un funcional truco o dos hablar 🙂

    OriginalEl autor ZXX

  6. 0

    Aquí es lo que usamos en SQLServer y funciona como un encanto:

    ...
    
      Dim X as Object = pbDr("TotAmt")  'dr is dim'ed as a DataReader
    
    ...
    
      Public Function pbDr(ByVal drName As String) As Object
    
        Dim SQLError As SqlClient.SqlException
    
        Dim IsNull As Boolean
    
        Dim Ordinal, DispNbr As Integer
    
        Try
          Ordinal = dr.GetOrdinal(drName)
          IsNull = dr.IsDBNull(Ordinal)
          If IsNull Then
            Dim Dbtype As String = dr.GetFieldType(Ordinal).ToString
            If Dbtype = "System.String" Then
              Return ""
            ElseIf Dbtype = "System.Int32" _
             OrElse Dbtype = "System.Double" _
             OrElse Dbtype = "System.Decimal" _
             OrElse Dbtype = "System.Int16" Then
              Return 0
            Else
              MsgBox("Print This Screen And Send To Support" _
               & "pbdr-Object = " & Dbtype, MsgBoxStyle.Critical)
              Return ""
            End If
          Else
            Return dr(Ordinal)
          End If
    
        Catch sqlerror
          Call DispSQLError(SQLError, "pbDr")
          pbDr = ""
        End Try
    
      End Function

    OriginalEl autor Price Brattin

  7. -1

    Hoy en día, usted probablemente querrá la nula si la base de datos devuelve y, como tal, debe usar una Nullable<int>:

    public static class Extensions
    {
        public static int? GetNullableInt32(this SqlDataReader reader, int ordinal)
        {
            if (reader.IsDBNull(ordinal))
                return null;
    
            return reader.GetInt32(ordinal);
        }
    
        public static long? GetNullableInt64(this SqlDataReader reader, int ordinal)
        {
            if (reader.IsDBNull(ordinal))
                return null;
    
            return reader.GetInt64(ordinal);
        }
    }

    OriginalEl autor Daniel Hilgarth

Dejar respuesta

Please enter your comment!
Please enter your name here