web-dev-qa-db-fra.com

L'objet ne peut pas être converti de DBNull vers d'autres types

L'objet ne peut pas être converti de DBNull vers d'autres types.

J'ai une fonction suivante qui jette l'erreur ci-dessus. Je gère toutes les procédures null en magasin et dans le code C #.

Alors, où trouve-t-on cette erreur?

Je peux voir l'erreur dans le bloc catch. Mais je ne comprends pas quelle ligne dans ce qui suit create () obtienne 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;
    }
}
36
Jaison

Je pense que votre paramètre de sortie revient avec une valeur DBNull. Ajouter un chèque pour ça comme ça

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

Je soupçonne que la ligne

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

est la cause du problème. Est-il possible que le op_Id la valeur est définie sur null par la procédure stockée?

Pour vous en prémunir, utilisez le 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
}
15
IndigoDelta

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

2
Daniel Hilgarth

Raison de l'erreur: Dans un langage de programmation orienté objet, la valeur 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 actuel auquel j'ai fait face à une 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 la valeur null, il est recommandé d’utiliser la classe DBNull au lieu de spécifier simplement comme null, comme dans le langage C #.

2
Karthik Elumalai

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

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

Pour les autres qui arrivent sur cette page à partir de Google:

DataRow a également une fonction .IsNull("ColumnName")

    public DateTime? TestDt; 
    public Parse(DataRow row)
    {
        if (!row.IsNull("TEST_DT"))
            TestDt = Convert.ToDateTime(row["TEST_DT"]);
    }
0
JoeF

J'ai fait face à ce problème aujourd'hui et l'ai résolu en vérifiant la classe de mappage. J'avais une classe qui avait 5 propriétés à laquelle 5 colonnes renvoyées de procédure stockée étaient en cours de mappage. Ces propriétés étaient non nullables et en raison desquelles je recevais l'erreur. Je les ai rendus nuls et le problème résolu.

    public int? Pause { get; set; }
    public int? Delay { get; set; }
    public int? Transition { get; set; }
    public int? TransitionTime { get; set; }
    public int? TransitionResolution { get; set; }

Ajoutée "?" avec le type de données pour les rendre nullable.

Deuxièmement, j'ai également ajouté la vérification isNull dans la procédure stockée, ainsi que les suivantes:

    isnull(co_pivot.Pause, 0) as Pause,
    isnull(co_pivot.Delay, 0) as Delay,
    isnull(co_pivot.Transition, 0) as Transition,
    isnull(co_pivot.TransitionTime, 0) as TransitionTime,
    isnull(co_pivot.TransitionResolution, 0) as TransitionResolution

J'espère que ça aide quelqu'un.

0
Harry .Naeem