6
votes

System.InvalidcastException: L'objet ne peut pas être jeté de DBNULL à d'autres types

J'ai une exception dans mon code. J'ai déjà essayé de changer mon INT64 en int32 mais cela ne le change pas.

Dans la base de données, les cellules qui représentent "colonne_id" ont un numéro de type de données. P>

Le problème est à la ligne 7 Ce code: p> xxx pré>

L'erreur est: p>

System.InvalidCastException: Object cannot be cast from DBNull to other types.
   at System.DBNull.System.IConvertible.ToInt64(IFormatProvider provider)
   at System.Convert.ToInt64(Object value)
   at Software_Client.FormSendReceiveRecipe.dataGridView_ArticleINVIA_CellDoubleClick(Object sender, DataGridViewCellEventArgs e)


4 commentaires

L'exception vous indique exactement ce que vous devez savoir - lignes [e.rowindex] .Cells ["colonne_machine"]. Valeur est dbnull , et vous ne pouvez pas lancer dbnull à n'importe quel autre type. Vérifiez si votre colonne_machine COREL est dbnull avant d'appeler convert.toint32


Vous voulez dire que je n'ai besoin que de vérifier si la valeur est dbnull? et si c'est le cas? J'ai vérifié sur la base de données la valeur et n'est pas null


@LaxEdur correct, ce n'est pas null , c'est dbnull . Les deux sont différents.


En règle générale, si vous pouvez appeler à un objet, vous devez l'entourer avec un bloc utilisant un bloc: en utilisant (formespenpuis PopupNote = New FormRecipenote (id_macchina, "MODIFICA", ID_RIGA, 0)) {PopupNote.ShowdiDialog (cette); }


3 Réponses :


4
votes

Vous pouvez modifier la ligne problématique en: xxx pré>

Ceci donnera la valeur par défaut de INT (0) à la variable id_macchina code> si la valeur de la colonne colonne_machine code> est null dans la base de données (sera dbnull code> in c #) p>

Essayez ceci: p>

object aa = DBNull.Value;
int a = (aa as int?).GetValueOrDefault();


12 commentaires

Ce n'est pas un nullable int , il utilise dbnull au lieu de null .


Mais cela résoudra le problème :) Vous décrivez la cause du problème et je résolvez le problème !! Pourquoi le vote DONW!


Je n'ai pas dit que c'était nullable, mais ma ligne résoudra le problème, j'ai utilisé nullable pour utiliser le casting en toute sécurité (comme).


Essayez ceci: objet aa = dbnull.value; int a = (aa comme int?). Getvalueordfault ();


@svick en fait, techniquement, cela fonctionnera. Depuis dbnull de type int ou int? La distribution échoue et le résultat de comme est-ce que Il renvoie null pendant qu'un int est réussi. Cependant, il est assez confus car il donne la fausse impression que cela ne fonctionnera pas, et ce n'est pas clair ce que c'est vraiment en train de le faire, la lisibilité en souffre considérablement.


@Servy ah, tu as raison. J'ai essayé dbnull.value comme INT? , qui n'a pas fonctionné, mais c'est différent (car la valeur est saisie comme objet ).


Thanx @Servy à votre simple !!


@Msakhersawan vous avez raison, cela fonctionnera. Mais je suis d'accord avec Servy qu'il est très déroutant. En outre, il peut masquer un bug: si la valeur est en réalité un autre type, vous voulez une erreur forte, pas de retour en silence null .


Une fois que c'est un idiome commun, cela cesse d'être déroutant. J'ai vu cela suffisamment utilisé pour ne pas être confus par celui-ci, donc +1 de moi. Le point sur le traitement silencieusement différents types (disent que les modifications du type de serveur, et que vous obtenez maintenant un long ) comme null est un point valide, cependant.


Vous avez raison @hvd, je vais éditer ma réponse pour décrire ceci :)


Il n'y a vraiment aucune raison de passer par int? (AKA nullable ) Si vous allez simplement appeler getvalueordfault () dessus. C'est un exercice simple d'écrire une belle méthode d'extension commode pour faire exactement la même chose, mais avec une sémantique beaucoup plus simple. Vous pouvez même aller plus loin dans la méthode de l'extension pour effectuer plus de vérification des erreurs, etc. pour des objets qui ne sont ni égaux à dbnull ni convertibles au type souhaité. IMO, ces cas ne doivent pas être ignorés silencieusement car ils seraient en appelant comme int? etc.


IMHO, cette conversation entière sur la coulée vers int? et si cela fonctionnera et si c'est une bonne idée ou non est complètement hors sujet. Cela ne fait vraiment rien pour l'OP qui essaie simplement de comprendre pourquoi Dbnull s'affiche dans la cellule lorsque la valeur de la base de données n'est pas nulle (au moins aussi loin que possible). Il serait donc plus utile de l'aider à aller au fond de son problème réel plutôt que de débattre du meilleur paradigme à utiliser pour détecter et convertir des dbnulls. La question est de savoir pourquoi la cellule NULL / DBNULL est-elle en premier lieu et comment l'OP peut-il trouver la source du bogue?



9
votes

Comme le dit le message d'erreur, la valeur de la cellule est dbnull.value et il ne peut pas convertir de ce que vous voulez que ce soit (dans ce cas un long < / code> ou un int ). Vous devez rechercher dbnull avant de convertir / casser le numéro: xxx

Parce que cela ajoute des frais généraux ennuyeux, si vous le faites beaucoup, vous voudrez probablement faire Une méthode d'assistant qui le fait pour vous. xxx

alors votre code peut être: xxx


2 commentaires

@Msakhersawan par un montant entièrement négligeable. En outre, vous affirmez que cela ne fonctionnera pas (même si cela le fera).


@Servy merci pour la réponse, demain je verrai si je peux obtenir avec votre code pour résoudre le problème



1
votes

Je suis un peu confus par certains de vos commentaires. Comme par exemple, dans votre code, le commentaire indique que la ligne contenant toint32 est l'endroit où l'erreur se produit, mais le message d'erreur indique clairement que l'erreur est lancée à partir de toint64 .

En outre, vous avez dit que la valeur de la base de données n'est pas nulle. Si cela est vrai, vous ne recevriez pas la valeur DBNULL, il serait donc utile d'étendre votre code un peu afin de pouvoir pouvoir placer des points d'arrêt et inspecter les valeurs dans les cellules directement avant d'essayer de les convertir.

J'ai posté un exemple de code ci-dessous que vous pouvez utiliser, y compris une fonction d'aide de conversion que vous pourriez trouver utile. xxx

Je veux aussi effacer Un commentaire que j'ai vu au-dessus de cela dit "... ce n'est pas null, c'est dbnull. Les deux sont différents". Cette déclaration est vraie en général, en C #, mais elle est en fait trompeuse dans le contexte qu'il a été écrit. Il a été écrit en réponse au commentaire précédent qui a déclaré "[i] [I] vérifié sur la base de données la valeur et n'est pas null". Pour plus de clarification, une null dans un champ de base de données est représentée par DBNULL dans la plupart des fournisseurs de base de données .NET. Ainsi, en fait, une valeur nulle dans la base de données est généralement la même que DBNULL en C #. Donc, si l'OP est correct en disant que la valeur de la base de données n'est pas nulle, elle est-elle suivie que la valeur de la cellule ne doit pas être dbnull.

Bien sûr, il est toujours vrai que null n'est pas identique que dbnull , alors vérifiant pour voir si un objet est NULL ne détermine pas s'il est dbnull ou non, (mais ce n'est pas ce que dit l'OP).

comme une note finale, la méthode d'extension que j'ai écrite, frtdb , comprend un paramètre facultatif pour une valeur par défaut Valeur de retour dans le cas où l'objet passé est dbnull. Ceci peut être utilisé comme suit: xxx

Selon vos préférences personnelles, le paradigme ci-dessus pourrait être plus facile à comprendre que la version nullable décrite dans d'autres réponses. < / p>


0 commentaires