简体   繁体   English

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

[英]DataRow.Field<T>(string Column) throws invalid cast exception

Good day, 美好的一天,

IDE Visual Studio 2010 IDE Visual Studio 2010
.NET 3.5 .NET 3.5
Platform WinForms 平台 WinForms

The SO question " difference between getting value from DataRow " refers. SO问题“ 从DataRow获得价值之间的区别 ”是指。

I have a database table with a column [ID] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY . 我有一个带有表[ID] INT IDENTITY(1, 1) NOT NULL PRIMARY KEY的数据库表。 When querying this table and storing the values in local variables I get an invalid cast exception; 当查询该表并将值存储在局部变量中时,我得到一个无效的强制转换异常。 sample code: 样例代码:

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

When stepping the execution and performing a "Quick Watch" on the faulty line I discovered that, by changing the line to drSource.Field<object>("ID") , the cell value type is that of short and not of int . 当在错误的行上逐步执行并执行“快速监视”时,我发现,通过将行更改为drSource.Field<object>("ID") ,单元格值类型为short而不是int Why would this happen when, in the table definition, this is clearly and int ? 为什么会发生这种情况时,在表定义中,这显然是和int Furthermore, short should be implicitly converted to int since short is smaller and should "fit" right? 此外,因为short较小,所以应该将short隐式转换为int并且“合适”吗?

If your column is a nullable int, but you are trying to assign to an int, with a default value of 0 : 如果您的列是可为null的int,但您尝试分配给一个int,其默认值为0:

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

If your column is a nullable int, and you want to assign to a nullable int : 如果您的列是可为null的int,并且您想分配给可为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"];

According to implementation of Field extension, your field has DbNull value. 根据字段扩展的实现,您的字段具有DbNull值。

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

UnboxT is a private class that provides methods for converting object to T. In your case ValueField converter is used: 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"));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM