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;
}
}
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);
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
}
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
...
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 #.
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;
}
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"]);
}
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.