¿Cuál es la mejor práctica para manejar null int / char desde una base de datos SQL?

StackOverflow https://stackoverflow.com/questions/318567

  •  11-07-2019
  •  | 
  •  

Pregunta

Tengo una base de datos que contiene el perfil opcional de un usuario. En el perfil tengo cadenas, char (para M o F) e ints.

Me encontré con un problema en el que trato de poner el sexo del usuario en la propiedad de mi objeto Profile, y la aplicación se bloquea porque no sabe cómo manejar un valor nulo devuelto.

He intentado transmitir los datos al tipo apropiado

char sex = (char)dt.Rows[0]["Sex"];

Lo cual no solucionó mi problema. Luego intenté cambiar los tipos a Nullable y Nullable y obtuve problemas de conversión de todos modos. Mi solución actual que pude encontrar es la siguiente:

object.sex = null;  
if(dt.Rows[0]["Sex"] != DBNull.Value)
      object.sex = (char)dt.Rows[0]["Sex"];
object.WorkExt = null;
if(dt.Rows[0]["WorkExt"] != DBNull.Value)
      object.WorkExt = (int)dt.Rows[0]["WorkExt"];

¿Hay una manera más simple o mejor de hacer esto? ¿O estoy más o menos en el camino correcto?

¿Fue útil?

Solución

la respuesta de rotard (use Is<ColumnName>Null()) solo funciona para conjuntos de datos escritos.

Para conjuntos de datos sin tipo, debe usar uno de los patrones en el siguiente código. Si este código no es definitivo, avíseme y lo editaré hasta que lo sea. Esta es una pregunta extremadamente común a la que realmente debería haber una sola respuesta correcta.

using System.
using System.Data;

class Program
{
    static void Main(string[] args)
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("test", typeof (char));
        dt.Columns["test"].AllowDBNull = true;

        DataRow dr = dt.Rows.Add();
        char? test;

        try
        {
            test = (char?)dr["test"];
        }
        catch (InvalidCastException)
        {
            Console.WriteLine("Simply casting to a nullable type doesn't work.");
        }

        test  = dr.Field<char?>("test");
        if (test == null)
        {
            Console.WriteLine("The Field extension method in .NET 3.5 converts System.DBNull to null.");                
        }

        test = (dr["test"] is DBNull) ? null : (char?) dr["test"];
        if (test == null)
        {
            Console.WriteLine("Before .NET 3.5, you have to check the type of the column's value.");
        }

        test = (dr["test"] == DBNull.Value) ? null : (char?) dr["test"];
        if (test == null)
        {
            Console.WriteLine("Comparing the field's value to DBNull.Value is very marginally faster, but takes a bit more code.");
        }

        // now let's put the data back

        try
        {
            dr["test"] = test;
        }
        catch (ArgumentException)
        {
            Console.WriteLine("You can't set nullable columns to null.");
        }

        dr.SetField("test", test);
        if (dr["test"] is DBNull)
        {
            Console.WriteLine("Again, in .NET 3.5 extension methods make this relatively easy.");
        }

        dr["test"] = (object)test ?? DBNull.Value;
        if (dr["test"] is DBNull)
        {
            Console.WriteLine("Before .NET 3.5, you can use the null coalescing operator, but note the awful cast required.");
        }


        Console.ReadLine();
    }
}

Otros consejos

¡

tipos anulables fueron diseñados solo para este propósito! use 'como char?' en lugar de '(char?)'

class Foo {
    char? sex;
}
Foo object;

object.sex = dt.Rows[0]["Sex"] as char?;

¿Es dt una tabla de datos ADO.Net 2? ¿No puedes hacer algo como:

if(dt.Rows[0].IsSexNull()) {} else {}

? Además, suponiendo que tenga control sobre su base de datos, ¿no tendría más sentido usar un bit en lugar de una cadena?

que tal:

    internal static T CastTo<T>(object value)
    {
        return value != DBNull.Value ? (T)value : default(T);
    }

y luego úsalo como:

        return new EquipmentDetails(
            CastTo<int>(reader["ID"]),
            CastTo<int>(reader["CategoryID"]),
            CastTo<string>(reader["Description"]));

etc ...

Lo haría más o menos como lo hiciste tú. Escribiría una función para ello:

Algo que hace:

object.sex = handle(dt.Rows[0]["Sex"]);

Y en el control haces la comprobación de == DBNull.Value.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top