web-dev-qa-db-fra.com

C # ADO.NET: nulls et DbNull - y a-t-il une syntaxe plus efficace?

J'ai un DateTime? que j'essaie d'insérer dans un champ à l'aide d'un DbParameter. Je crée le paramètre comme ceci:

DbParameter datePrm = updateStmt.CreateParameter();
datePrm.ParameterName = "@change_date";

Et puis je veux mettre la valeur du DateTime? dans le dataPrm.Value tout en tenant compte de nulls.

Je pensais au départ que je serais intelligent:

datePrm.Value = nullableDate ?? DBNull.Value;

mais cela échoue avec l'erreur

Opérateur '??' ne peut pas être appliqué aux opérandes de type 'System.DateTime?' et 'System.DBNull'

Je suppose donc que cela ne fonctionne que si le deuxième argument est une version non nullable du premier argument. Alors je suis allé chercher:

datePrm.Value = nullableDate.HasValue ? nullableDate.Value : DBNull.Value;

mais ça ne marche pas non plus:

Le type d'expression conditionnelle ne peut pas être déterminé car il n'y a pas de conversion implicite entre 'System.DateTime' et 'System.DBNull'

Mais je ne veux pas convertir entre ces types!

Jusqu'à présent, la seule chose que je puisse obtenir au travail est:

if (nullableDate.HasValue)
  datePrm.Value = nullableDate.Value;
else
  datePrm.Value = DBNull.Value;

Est-ce vraiment la seule façon d'écrire ça? Existe-t-il un moyen d'obtenir un one-liner en utilisant l'opérateur ternaire pour travailler?

pdate: Je ne comprends pas vraiment pourquoi ?? la version ne fonctionne pas. MSDN dit:

Le ?? L'opérateur renvoie l'opérande de gauche s'il n'est pas nul, sinon il renvoie l'opérande de droite.

C'est exactement ce que je veux!

pdate2: Eh bien, c'était un peu évident à la fin:

datePrm.Value = nullableDate ?? (object)DBNull.Value;
48
Stewart Johnson

Ah ha! J'ai trouvé une solution encore plus efficace que celle de @ Trebz!

datePrm.Value = nullableDate ?? (object)DBNull.Value;
62
Stewart Johnson

Si vous utilisez SQLServer, le System.Data.SqlTypes l'espace de noms contient quelques classes utilitaires qui évitent le transtypage de type ennuyeux. Par exemple, au lieu de cela:

var val = (object) "abc" ?? DBNull.Value;

vous pouvez écrire ceci:

var val = "abc" ?? SqlString.Null;
6

Cela fonctionnerait si vous utilisiez

datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : DBNull.Value;
5
dnolan

Si vous utilisez C # 3.0, vous pouvez créer une méthode d'extension pour le faire facilement:

public static class DBNullableExtensions
{
    public static object ToDBValue<T>(this Nullable<T> value) where T:struct
    { 
        return value.HasValue ? (object)value.Value : DBNull.Value;
    }
}


class Program
{
    static void Main(string[] args)
    {
        int? x = null;

        Console.WriteLine(  x.ToDBValue() == DBNull.Value );
    }
}
5
Pop Catalin

Je pense que l'erreur avec votre deuxième tentative est due à nullableDate.Value et DBNull.Value étant des types différents et à l'opérateur ternaire ayant besoin de choisir un type à retourner dans les deux cas. Je n'ai pas l'environnement pour tester cela mais je pense que cela devrait fonctionner pour vous:

datePrm.Value = nullableDate.HasValue ? (object)nullableDate.Value : (object)DBNull.Value;
1
Dan

La façon dont je le fais, c'est que j'ai une classe d'utilité statique qui passe juste en revue et vérifie si la valeur du paramètre est nulle, puis je définis la valeur pour faire DBNull. Je fais juste ça avant d'appeler l'Execute.

0
Darren Kopp