C# System.InvalidCastException:无法将对象从DBNull强制转换为其他类型
我的代码中有一个异常。我已经尝试将int64更改为int32,但这并没有改变它 在数据库中,表示“column_ID”的单元格具有数据类型编号 此代码中的第7行存在问题:C# System.InvalidCastException:无法将对象从DBNull强制转换为其他类型,c#,oracle,C#,Oracle,我的代码中有一个异常。我已经尝试将int64更改为int32,但这并没有改变它 在数据库中,表示“column_ID”的单元格具有数据类型编号 此代码中的第7行存在问题: private void dataGridView_ArticleINVIA_CellDoubleClick(object sender, DataGridViewCellEventArgs e) { if (e.RowIndex >= 0 && e.RowIndex <= (sender
private void dataGridView_ArticleINVIA_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
if (e.RowIndex >= 0 && e.RowIndex <= (sender as DataGridView).Rows.Count - 1)
{
try
{
Int64 id_riga = Convert.ToInt64((sender as DataGridView).Rows[e.RowIndex].Cells["column_ID"].Value);
//Exception thrown here:
int id_macchina = Convert.ToInt32((sender as
DataGridView).Rows[e.RowIndex].Cells["column_Machine"].Value);
FormRecipeNote PopUpNote = new FormRecipeNote(id_macchina,
"MODIFICA", id_riga, 0);
PopUpNote.ShowDialog(this);
PopUpNote.Dispose();
}
catch (Exception Exc)
{
FormMain.loggerSoftwareClient.Trace(this.Name + " " + Exc);
}
//DataGrid_ArticleINVIA();
}
}
有人能帮我解决这个问题吗?您可以将有问题的行更改为:
int id_macchina = ((sender as DataGridView).Rows[e.RowIndex].Cells["column_Machine"].Value as int?).GetValueOrDefault();
如果列column\u machina
的值在数据库中为空(在C中为DBNull
),则这将为变量id\u macchina
提供int(0)的默认值
试试这个:
object aa = DBNull.Value;
int a = (aa as int?).GetValueOrDefault();
它会成功的!如果列为DBNull
,则该值将为0
*编辑*
但是尝试使用其他方法,这可能会隐藏一些错误,例如更改数据类型,如果类型很长且在数据库中不是int,则始终会将0分配给变量,这在过去发生在我身上,这要感谢@hvd在他的注释中指出了这一点。正如错误消息所说,单元格的值为
DBNull.value
,它无法从该值转换为您想要的值(在本例中为long
或int
)。在转换/转换数字之前,您需要检查DBNull
:
Int64 id_riga = 0;
object value = (sender as DataGridView).Rows[e.RowIndex].Cells["column_ID"].Value;
if(value != DBNull.Value)
id_riga = Convert.ToInt64(value);
因为这会增加一些恼人的开销,如果你做了这么多,你可能会想要一个帮助器方法来为你做这件事
public static long? getLongFromDB(object value)
{
if (value == DBNull.Value) return null;
return Convert.ToInt64(value);
}
那么您的代码可以是:
Int64 id_riga = getLongFromDB((sender as DataGridView).Rows[e.RowIndex].Cells["column_ID"].Value)
.GetValueOrDefault();
你的一些评论让我有点困惑。例如,在您的代码中,注释表明包含
ToInt32
的行是发生错误的地方,但错误消息清楚地显示错误是从ToInt64
中抛出的
另外,您说过数据库中的值不是null。如果这是真的,那么就不会得到DBNull值,因此可能值得对代码进行一点扩展,以便在转换之前可以放置一些断点并直接检查单元格中的值
我在下面发布了一些您可以使用的示例代码,包括一个您可能会觉得有用的转换助手函数
//--------- inside the try block of your event handler -----------//
var row = (sender as DataGridView).Rows[e.RowIndex];
object objId = row.Cells["column_ID"].Value;
object objMachine = row.Cells["column_Machine"].Value;
// place a breakpoint on the line below,
// so you can inspect the "obj..." values above to see
// if they are DBNull or not.
var id_riga = objId.FromDb<Int64>();
var id_macchina = objMachine.FromDb<Int32>();
//-----------continue your code here---------//
//----outside the form class, possibly in a separate file -----/
static class DbObjectExtensions {
public static T FromDb<T>(this object dbObj, T defaultValueIfNull = default(T)) where T : IConvertible {
if (Convert.IsDBNull(dbObj))
return defaultValueIfNull;
if (dbObj is T)
return (T)dbObj;
return (T)Convert.ChangeType(dbObj, typeof(T));
}
}
根据您自己的个人偏好,上述范例可能比其他答案中描述的可空版本更容易理解。例外情况是告诉您确切需要知道的内容-
行[e.RowIndex]。单元格[“column\u Machine”]。Value
为DbNull
,并且不能将DbNull
强制转换为任何其他类型。在调用Convert.ToInt32
之前,检查您的column\u机器
单元格是否为DbNull
。您的意思是我只需要检查值是否为DbNull?如果是这样的话?我在数据库中检查了该值,但没有NULL@Laxedur正确,它不是null
,而是DBNull
。这两个是不同的。根据经验,如果你可以对一个对象调用Dispose,你应该用一个using块围绕它:using(FormRecipeNote PopUpNote=new-FormRecipeNote(id_macchina,“MODIFICA”,id_riga,0)){PopUpNote.ShowDialog(this);}
它不是一个可为null的int
,它使用的是DBNull
而不是null
。但这将解决问题:)您正在描述问题的原因,我正在解决问题!!为什么不投票@实际上,从技术上讲,它会起作用的。由于DBNull
不是int
或int?
类型,转换失败,而as
的结果是,当成功转换实际的int
时,它返回null
。然而,它非常令人困惑,因为它给人一种错误的印象,认为它不起作用,而且不清楚它到底在做什么,所以可读性受到很大影响。@MSakherSawan你是对的,它会起作用。但我同意Servy的观点,这很令人困惑。此外,它还可能隐藏一个bug:如果该值实际上是其他类型的,那么您需要一个响亮的错误,而不是静静地返回null
。一旦它成为一个常见的习惯用法,它就不再令人困惑。我已经看到了足够多的使用,不会被它搞糊涂,所以+1来自我。将不同类型(例如服务器类型更改,您现在得到一个long
)作为null
进行静默处理是一个有效的观点,但是@MSakherSawan的数量可以忽略不计。此外,您断言它将不起作用(即使它会起作用)。@Servy感谢您的回复,明天我将看看是否可以使用您的代码来解决此问题
//--------- inside the try block of your event handler -----------//
var row = (sender as DataGridView).Rows[e.RowIndex];
object objId = row.Cells["column_ID"].Value;
object objMachine = row.Cells["column_Machine"].Value;
// place a breakpoint on the line below,
// so you can inspect the "obj..." values above to see
// if they are DBNull or not.
var id_riga = objId.FromDb<Int64>();
var id_macchina = objMachine.FromDb<Int32>();
//-----------continue your code here---------//
//----outside the form class, possibly in a separate file -----/
static class DbObjectExtensions {
public static T FromDb<T>(this object dbObj, T defaultValueIfNull = default(T)) where T : IConvertible {
if (Convert.IsDBNull(dbObj))
return defaultValueIfNull;
if (dbObj is T)
return (T)dbObj;
return (T)Convert.ChangeType(dbObj, typeof(T));
}
}
//assuming -1 isn't a valid
var id_riga = objId.FromDb<Int64>(-1); id
if (id_riga == -1) { /*handle case for null db value*/ }