Si je fais quelque chose comme: est un bon moyen de vérifier les valeurs null sans utiliser l'essai / prise? C'est juste que je ne me soucie pas si la valeur "Col1" est nulle ou si "Col1" n'existait pas, ou s'il n'y avait pas de rangées retournées, ou si la table n'existe pas! P> < p> Peut-être que je devrais m'occuper? :)
Peut-être essayer / attraper est la meilleure façon d'aborder cela, mais je me demandais simplement s'il y avait une autre façon de le faire? P> Merci! P> P>
14 Réponses :
Vous recherchez DBNULL.Value E.G.
if (ds.Tables[0].Rows[0]["col1"] != DBNull.Value)
Problèmes de: NULL DataSet, pas de tables, pas de lignes, etc.
Il est un peu étrange de ne pas se soucier de la table ou de la colonne. p>
C'est une pratique beaucoup plus normale à attendre Et la meilleure façon de vérifier que les valeurs NULL sont avec Tableau [0] .rows.count == 0 code> par exemple. p>
si (...) ... sinon ... code>.
Le pire moyen est d'attendre des exceptions (de quelque manière que ce soit). p>
Je suppose. C'est juste que même après avoir écrit tout le code indiquant "s'il y a un jeu de données et s'il y a une table et s'il y a une ligne et s'il y a une colonne", le résultat final est toujours vraiment intéressé Pour obtenir une valeur ou non! Il existe sûrement un moyen d'augmenter la lisibilité du code ici?
«Augmentez la lisibilité du code ici» - une meilleure conception, et peut-être moins de données de données. Vos requêtes doivent toujours produire un type (un peu) défini, de sorte que les tables et les colonnes manquantes peuvent être évitées.
C'était juste un exemple. Nous avons tous rencontré la situation (pas nécessairement avec des jeux de données) où vous avez des objets imbriqués et que vous devez dire si obj! = Null && obj.obj1! = Null && obj.obj1.obj2! = Null puis obtenir obj.obj1. obj2.value. Droite?
@JQWha, il n'y a pas de raccourci. Il a souvent été demandé à un opérateur de la forme ?. Code> où vous pouviez dire
a? .B code>, et si
a code> a été null, ceci Ne lanceriez pas, la sortie serait définie comme null ou peut-être la valeur par défaut du type de
B code>. Mais cela ne fait actuellement pas partie de la langue ni je suis conscient si cela est même une possibilité pour une future version.
Oui ça arrive. Mais quand il est fréquent ou plus de 2 niveaux de profondeur, je commence à regarder en arrière au design.
@Anthony - Je pensais alors :(. Merci.
@Henk - Je sais ce que vous impliquez, mais je n'ai jamais acheté le commentaire de "C'est ton design". Il est trop académique d'assumer la pureté = la simplicité et la poursuite des conceptions académiquement pures conduit souvent à une complexité considérablement accrue.
"Complexité très accrue" - comme dans @redfilters réponse? Mais notez que j'ai essayé d'admettre les nuances de gris.
Il existe souvent des situations dans lesquelles il est complètement valable de dire "quelque part dans cette hiérarchie profonde d'objets, quelque chose peut ne pas être présent, ce qui signifie que tous les enfants ne seront pas présents, et ce n'est pas important, pourquoi ils ne sont pas présents, ils Ce n'est pas parce que c'est un état de choses logiquement cohérent ». Je cherche juste le soutien dans la langue pour quelque chose qui se passe tout le temps. Nous le prenons pour acquis que vous pouvez ajouter 2 à -3 et obtenir -1, sans vérifier que des chiffres sont inférieurs à 0, non?
Si vous parlez de collections, Linq gère cela assez élégamment. Dans d'autres contextes, vous avez généralement besoin d'un si par niveau, mais pas nécessairement dans une seule déclaration. La programmation structurée (méthodes d'empilement) fonctionne toujours.
Vous pourrez peut-être utiliser le ternaire nullable '??', mais je pense que la null qui est renvoyée est un "dbnull" et non "null".
L'exemple serait ... P >
string somevalue = ds.Tables[0].Rows[0]["col1"] ?? "";
Vous avez raison de ne pas être suffisant ici. Et c'est l'opérateur de coalescence nul, pas un "terary" ou ternaire. Celui que tout le monde appelle le ternaire est l'opérateur conditionnel, avec la forme a? B: C code>.
Vous devrez les vérifier tous pour NULL (ou d'autres types NULL) un par un, commençant au sommet (qui est le jeu de données) P>
si (DS! = null) Si (table! = null) ... p>
Vous pouvez le faire sans, mais votre code sera beaucoup plus susceptible aux erreurs. P>
Oui mais vois mon commentaire à Henk, ci-dessus.
if (ds == null || ds.Tables == null || ds.Tables.Count == 0 || ds.Tables[0].Rows == null || ds.Tables[0].Rows.Count == 0 || ds.Tables[0].Rows[0].IsNull("col1") ) //there is no data... ...
Peut-être commencer par si (world == null || ... code>
MDR. Ils ont vraiment besoin de construire quelque chose de récursif dans la langue.
d'un point de vue de maintenance, ce que vous faites est très souhaitable. P>
Sinon, vous devez: vérifier si DS est NULL, vérifiez s'il y a des tables dans l'ensemble de données, vérifiez s'il y a des lignes dans la table, vérifiez si la colonne existe, vérifiez pour voir S'il y a des données dans la colonne. P>
Il élimine certainement beaucoup de code fastidieux. P>
Si vous voulez vous assurer que votre code n'échoue pas, vous devrez réellement vérifier tous les éléments de la hiérarchie, par exemple:
Certaines vérifications:
string somevalue = String.Empty; if (ds.Tables.Count > 0) { System.Data.DataTable dt = ds.Tables[0]; if (dt.Rows.Count > 0) { System.Data.DataRow dr = dt.Rows[0]; if (dt.Columns.Count>0 && dt.Columns.Contains("col1")) { somevalue = dr["col1"].ToString(); } } }
Ce que j'ai utilisé dans le passé est une petite wrapper de tests nuls qui renvoient une valeur par défaut. Par exemple: utilisé: p>
Comme d'autres ont dit que la chaîne, quelqueévalue doit être exécutée après avoir été sûrement des lignes existantes en premier.
Je pense que vous devriez faire explicit que vous ne vous souciez pas de toutes ces choses, ce qui signifie que vous devez gérer chaque cas explicitement: c'est plus de code, mais pour moi, il communique le Intention plus clairement. p> p>
Mais «l'intention» est la récupération d'une valeur. Je ne pense pas que nous devrions préciser toutes les choses que nous ne nous soucions pas. Je ne suis pas un pirate informatique ou quoi que ce soit, mais il y a un équilibre à frapper, je pense?
Je dirais que l'intention est d'obtenir la valeur tout en manipulant un tas de cas spéciaux, "spécial" étant le mot clé ici. Ne pas se soucier de ces choses est important ici car ce n'est pas habituel. Bien sûr, vous pourriez (et devrait probablement) mettre cela dans une méthode et la réutiliser, rendre les frais généraux du code supplémentaire moins pertinent.
Je pense peut être monad est la meilleure chose pour cette situation (l'échantillon est de la source):
ds.With(x=>Tables[0]).With(x=>x.Rows).With(x=>x[0])...
Pouvez-vous élaborer comment vous avez fait fonctionner avec des jeux de données? Essayé de faire quelque chose de similaire, mais ça se brise et me donne un "..". => E.Tables [0]). Avec (E => E.Rows) .avec (E => E [0]). Avec (E => E ["Description"]). Tostring (); Code>
Si vous envoyez vraiment des ensembles de données, des index et des noms non validés aléatoires, vous pouvez faire une méthode d'assistance comme celle-ci: puis utilisez quelque chose comme getdataseSetValue ( ds, 0, 0, "col1") code>. p> p>
Quelle est votre alternative suggérée qui couvrira toutes les éventualités de l'accès requis sur les données?
@JQWha Modifiez la méthode à ce que vous envisageriez toutes les éventualités, puis appelez-la, j'ai essayé d'inclure toutes les éventualités que vous avez mentionnées, mais vous pouvez utiliser l'idée pour la mettre en œuvre.
DataSet ds = GetMyDataset(); string somevalue = ds != null ? ds.Tables[0].Rows[0]["col1"].ToString() : null;
Je déteste avoir à traiter d'une couche d'accès aux données qui ne me garantit pas un ensemble standard de résultats: une requête SQL donnée ou une procédure stockée doit être La bonne réponse consiste à corriger votre code d'accès aux données afin qu'il renvoie un schéma cohérent. P> omettant que, si je dois gérer le code Comme ça, je fais quelque chose comme ceci: p> Il est facile de déboguer soit dans le débogueur, soit via la journalisation. Donnez l'ensemble de 5 valeurs, vous pouvez facilement voir ce qui était présent et ce qui manquait. Il est facile de voir quelle hypothèse (contrainte?) A été violée. P> p>
Tout d'abord, ne faites pas un
générique code>. C'est une pratique horrible. Attrapez les erreurs que vous recherchez.
D'accord. Il a été juste lancé dans un exemple, mais c'est une sorte de même point - "N'utilisez pas la manipulation des erreurs pour attraper des choses qui ne sont pas vraiment des erreurs". Je cherchais peut-être peut-être que des techniques / mots-clés C # sont liées à ce problème.
Le peut-être monade semble être une bonne chose ici. codeproject.com/kb/cs/maybemonads.aspx