[c#] Lector de datos SQL: manejo de valores de columna nulos



Answers

Deberías usar el operador as combinado con el ?? operador para los valores predeterminados. Los tipos de valor deberán leerse como anulables y recibir un valor predeterminado.

employee.FirstName = sqlreader[indexFirstName] as string;
employee.Age = sqlreader[indexAge] as int? ?? default(int);

El operador as maneja la conversión, incluida la comprobación de DBNull.

Question

Estoy usando un lector de datos SQL para construir POCO desde una base de datos. El código funciona, excepto cuando encuentra un valor nulo en la base de datos. Por ejemplo, si la columna FirstName en la base de datos contiene un valor nulo, se lanza una excepción.

employee.FirstName = sqlreader.GetString(indexFirstName);

¿Cuál es la mejor manera de manejar valores nulos en esta situación?




Esta solución depende menos del proveedor y funciona con un SQL, OleDB y MySQL Reader:

public static string GetStringSafe(this IDataReader reader, int colIndex)
{
    return GetStringSafe(reader, colIndex, string.Empty);
}

public static string GetStringSafe(this IDataReader reader, int colIndex, string defaultValue)
{
    if (!reader.IsDBNull(colIndex))
        return reader.GetString(colIndex);
    else
        return defaultValue;
}

public static string GetStringSafe(this IDataReader reader, string indexName)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName));
}

public static string GetStringSafe(this IDataReader reader, string indexName, string defaultValue)
{
    return GetStringSafe(reader, reader.GetOrdinal(indexName), defaultValue);
}



Puede usar el operador condicional:

employee.FirstName = sqlreader["indexFirstName"] != DBNull.Value ? sqlreader[indexFirstName].ToString() : "";



No creo que haya un valor de columna NULL , cuando las filas se devuelven dentro de un lector de datos usando el nombre de la columna.

Si haces datareader["columnName"].ToString(); siempre le dará un valor que puede ser una cadena vacía ( String.Empty si necesita comparar).

Usaría lo siguiente y no me preocuparía demasiado:

employee.FirstName = sqlreader["columnNameForFirstName"].ToString();



cómo sobre la creación de métodos auxiliares

Para cadena

private static string MyStringConverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return "";

        return o.ToString();
    }

Uso

MyStringConverter(read["indexStringValue"])

Para Int

 private static int MyIntonverter(object o)
    {
        if (o == DBNull.Value || o == null)
            return 0;

        return Convert.ToInt32(o);
    }

Uso

MyIntonverter(read["indexIntValue"])

Fecha

private static DateTime? MyDateConverter(object o)
    {
        return (o == DBNull.Value || o == null) ? (DateTime?)null : Convert.ToDateTime(o);
    }

Uso

MyDateConverter(read["indexDateValue"])

Nota: para DateTime declara varialbe como

DateTime? variable;



Compruebe sqlreader.IsDBNull(indexFirstName) antes de intentar leerlo.




IsDbNull(int) suele ser mucho más lento que utilizar métodos como GetSqlDateTime y luego comparar con DBNull.Value . Pruebe estos métodos de extensión para SqlDataReader .

public static T Def<T>(this SqlDataReader r, int ord)
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return default(T);
    return ((INullable)t).IsNull ? default(T) : (T)t;
}

public static T? Val<T>(this SqlDataReader r, int ord) where T:struct
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? (T?)null : (T)t;
}

public static T Ref<T>(this SqlDataReader r, int ord) where T : class
{
    var t = r.GetSqlValue(ord);
    if (t == DBNull.Value) return null;
    return ((INullable)t).IsNull ? null : (T)t;
}

Úselos así:

var dd = r.Val<DateTime>(ords[4]);
var ii = r.Def<int>(ords[0]);
int nn = r.Def<int>(ords[0]);



Puede escribir una función genérica para verificar Null e incluir el valor predeterminado cuando es NULL. Llamar esto cuando lea Datareader

public T CheckNull<T>(object obj)
        {
            return (obj == DBNull.Value ? default(T) : (T)obj);
        }

Al leer el uso del lector de datos

                        while (dr.Read())
                        {
                            tblBPN_InTrRecon Bpn = new tblBPN_InTrRecon();
                            Bpn.BPN_Date = CheckNull<DateTime?>(dr["BPN_Date"]);
                            Bpn.Cust_Backorder_Qty = CheckNull<int?>(dr["Cust_Backorder_Qty"]);
                            Bpn.Cust_Min = CheckNull<int?>(dr["Cust_Min"]);
                         }



y / o usar operador ternario con asignación:

employee.FirstName = rdr.IsDBNull(indexFirstName))? 
                     String.Empty: rdr.GetString(indexFirstName);

reemplace el valor predeterminado (cuando sea nulo) según corresponda para cada tipo de propiedad ...




Estoy utilizando el código que figura a continuación para manejar celdas nulas en una hoja de Excel que se lee en una tabla de datos.

if (!reader.IsDBNull(2))
{
   row["Oracle"] = (string)reader[2];
}





Links