DataRow.Field<;T>;(字符串列)引发无效的强制转换异常

本文关键字:无效 转换 异常 lt Field gt DataRow 字符串 | 更新日期: 2023-09-27 18:29:03

你好,

IDEVisual Studio 2010
.NET3.5
平台WinForms

SO问题"从DataRow获取值之间的差异"指的是。

我有一个列为[ID] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY的数据库表。当查询这个表并将值存储在本地变量中时,我得到一个无效的强制转换异常;示例代码:

string sQuery = @"
    SELECT [ID], [Description]
    FROM [Sources]
    ORDER BY [Description] ";
using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{
    foreach (DataRow drSource in dtSources.Rows)
    {
        int iID = drSource.Field<int>("ID"); // InvalidCastException
        string sDescrption = drSource.Field<string>("Description");
    }
}

当执行并对故障线路执行"快速观察"时,我发现通过将线路更改为drSource.Field<object>("ID"),单元值类型为short,而不是int。当在表定义中,这显然是int时,为什么会发生这种情况?此外,short应该隐式转换为int,因为short更小,应该"合适"吗?

DataRow.Field<;T>;(字符串列)引发无效的强制转换异常

如果您的列是一个可为null的int,但您正试图分配给一个默认值为0:的int

using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{ 
    foreach (DataRow drSource in dtSources.Rows)'
    { 
        int iID = drSource.Field<int?>("ID") ?? 0; 
        string sDescrption = drSource.Field<string>("Description"); 
    }
}

如果你的列是一个可以为null的int,并且你想给它赋值:

using (DataTable dtSources = SQLHelper.Fetch(sQuery))
{
    foreach (DataRow drSource in dtSources.Rows)
    {
        int? iID = drSource.Field<int?>("ID");
        string sDescrption = drSource.Field<string>("Description"); 
    }
}

同意Richard的答案,只是更好地使用

int iID = Convert.ToInt32(drSource["ID"]);

出于好奇,如果您自己从键/值集合中显式转换它,会发生什么?

int iID = (int)drSource["ID"];

根据字段扩展的实现,您的字段具有DbNull值。

public static T Field<T>(this DataRow row, string columnName)
    {
        DataSetUtil.CheckArgumentNull<DataRow>(row, "row");
        return UnboxT<T>.Unbox(row[columnName]);
    }

UnboxT是一个私有类,它提供了将对象转换为T的方法。在您的例子中,使用了ValueField转换器:

private static class UnboxT<T>
{
    internal static readonly Converter<object, T> Unbox;
    static UnboxT()
    {
       DataRowExtensions.UnboxT<T>.Unbox =  
          new Converter<object, T>(DataRowExtensions.UnboxT<T>.ValueField);
    }
    private static T ValueField(object value)
    {
        if (DBNull.Value == value)
        {
            // You get this exception 
            throw DataSetUtil.InvalidCast(Strings.DataSetLinq_NonNullableCast(typeof(T).ToString()));
        }
        return (T) value;
    }
}

将行值转换为int变量的另一种方法是使用"object"并将其转换为Int32,如下所示:

int iID = Convert.ToInt32(row.Field<object>("ID"));