64 votes

Un objet ne peut pas être transféré de DBNull vers d'autres types.

L'objet ne peut pas être transféré de DBNull vers d'autres types.

J'ai une fonction suivante qui génère l'erreur ci-dessus. Je traite toutes les valeurs nulles dans la procédure de stockage et dans le code C#.

Alors où obtient-il cette erreur ?

Je peux voir l'erreur dans le bloc catch. Mais je ne comprends pas quelle ligne dans le create() suivant obtient l'erreur.

public Boolean Create(DataTO DataTO)
{
    IDbTrans transaction = null;
    IDbCmd IDbCmd;

    string EncryptedPassword = Encrypt(DataTO.txtPwd);
    Base dataAccCom = null;

    try
    {
        dataAccCom = Factory.Create();
        dataAccCom.OpenConnection();
        transaction = dataAccCom.BeginTransaction();
        IDbCmd = dataAccCom.CreateCommand("sp_Register", true);
        dataAccCom.AddParameter(IDbCmd, "op_Id", DbType.Int64, 0, ParameterDirection.Output);
        dataAccCom.AddParameter(IDbCmd, "p_dlstTitle", DbType.String, ReplaceNull(DataTO.dlstTitle));
        dataAccCom.AddParameter(IDbCmd, "p_txtFirstName", DbType.String, ReplaceNull(DataTO.txtFirstName));
        dataAccCom.AddParameter(IDbCmd, "p_txtMiddleName", DbType.String, ReplaceNull(DataTO.txtMiddleName));
        dataAccCom.AddParameter(IDbCmd, "p_txtLastName", DbType.String, ReplaceNull(DataTO.txtLastName));
        dataAccCom.AddParameter(IDbCmd, "p_txtDob", DbType.DateTime, DataTO.txtDob);
        dataAccCom.AddParameter(IDbCmd, "p_txtDesig", DbType.String, ReplaceNull(DataTO.txtDesig));
        dataAccCom.AddParameter(IDbCmd, "p_txtOFlatNo", DbType.String, ReplaceNull(DataTO.txtOFlatNo));
        dataAccCom.AddParameter(IDbCmd, "p_txtOBuild", DbType.String, ReplaceNull(DataTO.txtOBuild));
        dataAccCom.AddParameter(IDbCmd, "p_txtOPost", DbType.String, ReplaceNull(DataTO.txtOPost));
        dataAccCom.AddParameter(IDbCmd, "p_txtOArea", DbType.String, ReplaceNull(DataTO.txtOArea));
        dataAccCom.AddParameter(IDbCmd, "p_txtOCity", DbType.String, ReplaceNull(DataTO.txtOCity));
        dataAccCom.AddParameter(IDbCmd, "p_txtRBuild", DbType.String, ReplaceNull(DataTO.txtRBuild));
        dataAccCom.AddParameter(IDbCmd, "p_txtRPost", DbType.String, ReplaceNull(DataTO.txtRPost));
        dataAccCom.AddParameter(IDbCmd, "p_txtUserID", DbType.String,ReplaceNull(DataTO.txtUserID));
        dataAccCom.AddParameter(IDbCmd, "p_txtPwd", DbType.String, ReplaceNull(EncryptedPassword));
        dataAccCom.ExecuteNonQuery(IDbCmd);
        DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id"));
        transaction.Commit();
        return true;

    }
    catch (System.Exception ex)
    {
        if (transaction != null)
        {
            transaction.Rollback();
        }
        throw ex;
    }
    finally
    {
        transaction = null;
        if (dataAccCom != null)
        {
            dataAccCom.CloseConnection();
        }
        dataAccCom = null;
        IDbCmd = null;
    }
}

public string ReplaceNull(string value)
{
    if (value == null)
    {
        return "";
    }
    else
    {
        return value;
    }
}

public DateTime ReplaceNull(DateTime value)
{
    if (value == null)
    {
        return DateTime.Now;
    }
    else
    {
        return value;
    }
}

public double ReplaceNull(double value)
{
    if (value == null)
    {
        return 0.0;
    }
    else
    {
        return value;
    }
}

0 votes

Notez que votre ReplaceNull surcharges sur double y DateTime sont sans valeur. Les valeurs de ces types ne peuvent jamais être nulles et ne passeront donc jamais l'épreuve du if (value == null) condition.

0 votes

À moins qu'ils ne soient rendus invalides, bien sûr, mais c'est une autre histoire.

0 votes

Et avez-vous suivi la méthode ? Dans Visual Studio, envisagez de casser toutes les exceptions (Ctrl+Alt+E) et voyez quelle ligne pose réellement le problème.

84voto

Bala R Points 57552

Je pense que votre paramètre de sortie renvoie une valeur DBNull. Ajoutez une vérification pour cela comme ceci

var outputParam = dataAccCom.GetParameterValue(IDbCmd, "op_Id");
if(!(outputParam is DBNull))
     DataTO.Id = Convert.ToInt64(outputParam);

21 votes

Peut-être mieux Convert.IsDBNull() ?

0 votes

J'ai plusieurs valeurs entières dans ma requête. Puis-je raccourcir le processus ou dois-je le faire pour tout le monde ?

1 votes

@Alexander, j'espère que tu as trouvé une réponse avant, mais ça peut devenir assez moche d'obtenir plus court que ça, mais utiliser s ternaire fonctionnerait : DataTO.Id = dataAccCom.GetParameterValue(IDbCmd, "op_Id") == DBNull.Value ? null : Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id")) ;

18voto

IndigoDelta Points 1451

Je soupçonne que la ligne

DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id"));

est à l'origine du problème. Est-il possible que le op_Id est définie comme nulle par la procédure stockée ?

Pour s'en prémunir, utilisez l'option Convert.IsDBNull méthode. Par exemple :

if (!Convert.IsDBNull(dataAccCom.GetParameterValue(IDbCmd, "op_Id"))
{
 DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id"));
}
else 
{
 DataTO.Id = ...some default value or perform some error case management
}

6voto

Karthik Elumalai Points 1286

La raison de l'erreur : Dans un langage de programmation orienté objet, null signifie l'absence de référence à un objet. DBNull représente une variante non initialisée ou une colonne de base de données inexistante. Source : MSDN

Code réel dans lequel j'ai rencontré l'erreur :

Avant de changer le code :

    if( ds.Tables[0].Rows[0][0] == null ) //   Which is not working

     {
            seqno  = 1; 
      }
    else
    {
          seqno = Convert.ToInt16(ds.Tables[0].Rows[0][0]) + 1;
     }

Après avoir changé le code :

   if( ds.Tables[0].Rows[0][0] == DBNull.Value ) //which is working properly
        {
                    seqno  = 1; 
         }
            else
            {
                  seqno = Convert.ToInt16(ds.Tables[0].Rows[0][0]) + 1;
             }

Conclusion : lorsque la valeur de la base de données renvoie une valeur nulle, nous recommandons d'utiliser la classe DBNull au lieu de simplement spécifier une valeur nulle comme dans le langage C#.

5voto

Daniel Hilgarth Points 90722

Vous devez vérifier DBNull pas null . De plus, deux de vos trois ReplaceNull les méthodes n'ont pas de sens. double y DateTime sont non-nullables, donc la vérification de ces derniers pour les null sera toujours false ...

4voto

CrazyPyro Points 176

TryParse est généralement le moyen le plus élégant de gérer ce type de situation :

long temp = 0;
if (Int64.TryParse(dataAccCom.GetParameterValue(IDbCmd, "op_Id").ToString(), out temp))
{
   DataTO.Id = temp;
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X