6

我的代码中有一个例外。我已经尝试将我的 int64 更改为 int32 但这并没有改变它。

在数据库中,表示“column_ID”的单元格具有数据类型 NUMBER。

问题出在此代码的第 7 行:

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();
    }
}

错误是:

System.InvalidCastException: Object cannot be cast from DBNull to other types.
   at System.DBNull.System.IConvertible.ToInt64(IFormatProvider provider)
   at System.Convert.ToInt64(Object value)
   at Software_Client.FormSendReceiveRecipe.dataGridView_ArticleINVIA_CellDoubleClick(Object sender, DataGridViewCellEventArgs e)

有人可以帮我解决这个问题吗?

4

3 回答 3

9

正如错误消息所说,单元格的值是DBNull.Value并且它无法从它转换为您想要的任何值(在本例中为 along或 an 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();
于 2012-12-27T17:38:09.323 回答
4

您可以将有问题的行更改为:

int id_macchina = ((sender as DataGridView).Rows[e.RowIndex].Cells["column_Machine"].Value as int?).GetValueOrDefault();

id_macchina如果数据库中列的值为空,这将为变量提供默认值 int (0) column_Machine(将DBNull在 C# 中)

尝试这个:

object aa = DBNull.Value;
int a = (aa as int?).GetValueOrDefault();

它会起作用的!如果列是 ,则该值将为 0 DBNull

* 编辑 *

但是尝试使用别的东西,这样可能会隐藏一些bug,比如改变数据类型,如果类型是long而不是数据库中的int,会一直给变量赋值0,我以前也遇到过这种情况,感谢@hvd 在他的评论中表明这一点。

于 2012-12-27T17:36:58.960 回答
1

我对你的一些评论感到有些困惑。例如,在您的代码中,注释表明包含的行ToInt32是错误发生的位置,但错误消息清楚地表明错误是从内部抛出的ToInt64

另外,您说数据库中的值不为空。如果这是真的,您将不会获得 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));
    }
}

我还想澄清我在上面看到的一条评论,上面写着“......它不是空的,它是 DBNull。两者是不同的”。在 C# 中,该陈述通常是正确的,但在其编写的上下文中它实际上具有误导性。它是针对先前的评论写的,上面说“[I] 检查了数据库的值并且不是 NULL”。为澄清起见,在大多数 .Net 数据库提供程序中,数据库字段中的 NULL 由 DBNull 表示。所以实际上,数据库中的 NULL 值通常与 C# 中的 DBNull 相同。因此,如果 OP 正确地说数据库值不是 NULL,那么它确实遵循单元格值不应该是 DBNull。

当然,null与 不一样仍然是正确的DBNull,因此检查对象是否为 null 并不能确定它是否为 DBNull,(但这不是 OP 所说的)。

最后一点,我写的扩展方法FromDB,包含一个可选参数,用于在传递的对象是 DBNull 的情况下默认返回值。这可以按如下方式使用:

//assuming -1 isn't a valid 
var id_riga = objId.FromDb<Int64>(-1); id
if (id_riga == -1) { /*handle case for null db value*/ }

根据您自己的个人喜好,上述范例可能比其他答案中描述的 Nullable 版本更容易理解。

于 2012-12-27T18:25:02.387 回答