Объект нельзя отбрасывать из DBNull в другие типы
Объект нельзя отнести из DBNull к другим типам.
У меня есть следующая функция, которая выдает указанную выше ошибку. Я обрабатываю все нули в процедуре хранения и в коде С#.
Итак, откуда эта ошибка?
Я вижу ошибку в блоке catch. Но я не понимаю, какая строка в следующем create() получает ошибку.
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;
}
}
Ответы
Ответ 1
Я думаю, что ваш выходной параметр возвращается с использованием значения DBNull. Добавьте чек для этого, как этот
var outputParam = dataAccCom.GetParameterValue(IDbCmd, "op_Id");
if(!(outputParam is DBNull))
DataTO.Id = Convert.ToInt64(outputParam);
Ответ 2
Я подозреваю, что строка
DataTO.Id = Convert.ToInt64(dataAccCom.GetParameterValue(IDbCmd, "op_Id"));
вызывает проблему. Возможно ли, что значение op_Id
установлено в значение null хранимой процедурой?
Чтобы защитить его, используйте метод Convert.IsDBNull
. Например:
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
}
Ответ 3
Вам нужно проверить DBNull
, а не null
. Кроме того, два из ваших трех методов ReplaceNull
не имеют смысла. double
и DateTime
не имеют значения NULL, поэтому проверка их на null
всегда будет false
...
Ответ 4
Причина ошибки: на объектно-ориентированном языке программирования значение null означает отсутствие ссылки на объект. DBNull представляет собой неинициализированный вариант или несуществующий столбец базы данных. Источник: MSDN
Фактический код, с которым я столкнулся с ошибкой:
Перед изменением кода:
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;
}
После изменения кода:
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;
}
Заключение: когда значение базы данных возвращает нулевое значение, мы рекомендуем использовать класс DBNull вместо того, чтобы просто указывать нуль, как на языке С#.
Ответ 5
TryParse обычно самый элегантный способ справиться с этим типом вещей:
long temp = 0;
if (Int64.TryParse(dataAccCom.GetParameterValue(IDbCmd, "op_Id").ToString(), out temp))
{
DataTO.Id = temp;
}
Ответ 6
Для других, которые поступают на эту страницу из Google:
DataRow также имеет функцию .IsNull("ColumnName")
public DateTime? TestDt;
public Parse(DataRow row)
{
if (!row.IsNull("TEST_DT"))
TestDt = Convert.ToDateTime(row["TEST_DT"]);
}
Ответ 7
Я столкнулся с этой проблемой сегодня и решил ее, проверив класс отображения. У меня был класс, который имел 5 свойств, на которые отображались 5 столбцов, возвращаемых из хранимой процедуры. Эти свойства были не обнуляемыми, и из-за этого я получал ошибку. Я сделал их обнуляемыми, и проблема решена.
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; }
Добавлено "?" с типом данных, чтобы сделать их обнуляемыми.
Во-вторых, я также добавил проверку isNull в хранимой процедуре, а также:
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
Надеюсь, это кому-нибудь поможет.