Quelle est la meilleure pratique pour gérer null int / char à partir d'une base de données SQL?

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

  •  11-07-2019
  •  | 
  •  

Question

J'ai une base de données qui contient le profil optionnel de l'utilisateur. Dans le profil, j'ai des chaînes, des caractères (pour M ou F) et des ints.

J'ai rencontré un problème. J'essayais de définir le sexe de l'utilisateur dans la propriété de mon objet Profile. L'application se bloquait car elle ne savait pas comment gérer une valeur null renvoyée.

J'ai essayé de convertir les données dans le type approprié

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

Ce qui n'a pas résolu mon problème. J'ai ensuite essayé de changer les types en Nullable et Nullable et j'ai tout de même des problèmes de conversion. Ma solution actuelle que j'ai pu trouver est la suivante:

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"];

Existe-t-il un moyen plus simple ou meilleur de procéder? Ou suis-je à peu près sur la bonne voie?

Était-ce utile?

La solution

La réponse de

rotard (utilisez Is<ColumnName>Null()) ne fonctionne que pour les ensembles de données typés.

Pour les ensembles de données non typés, vous devez utiliser l'un des modèles du code suivant. Si ce code n'est pas définitif, faites le moi savoir et je le modifierai jusqu'à ce qu'il le soit. C’est une question extrêmement courante à laquelle il ne devrait y avoir qu’une seule bonne réponse.

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();
    }
}

Autres conseils

Les types

nullables ont été conçus uniquement à cette fin! utiliser 'comme personnage?' au lieu de '(char?)'

class Foo {
    char? sex;
}
Foo object;

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

Est-ce que dt est une table de données ADO.Net 2? Ne pouvez-vous pas faire quelque chose comme:

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

? De plus, en supposant que vous contrôliez votre base de données, n’auriez-vous pas plus de sens d’utiliser un bit plutôt que une chaîne?

que diriez-vous:

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

puis utilisez-le comme:

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

etc ...

Je le ferais à peu près comme vous l'avez fait. Je voudrais écrire une fonction pour cela:

Quelque chose qui fait:

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

Et dans le traitement, vous effectuez la vérification == DBNull.Value.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top