无法在 DataReader.GetString() 中将“System.Int32”类型的对象转换为“System.String”类型

Posted

技术标签:

【中文标题】无法在 DataReader.GetString() 中将“System.Int32”类型的对象转换为“System.String”类型【英文标题】:Unable to cast object of type 'System.Int32' to type 'System.String' in DataReader.GetString() 【发布时间】:2013-11-04 02:58:33 【问题描述】:

我试图将数据库中的数据添加到组合框。

        try
        
            SqlCeCommand com = new SqlCeCommand("select * from Category_Master", con);
            SqlCeDataReader dr = com.ExecuteReader();
            while(dr.Read())
                string name = dr.GetString(1);
                cmbProductCategory.Items.Add(name);
            
        
        catch(Exception ex)
        
            System.Windows.Forms.MessageBox.Show(ex.Message, System.Windows.Forms.Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
        

我得到以下异常:

无法将“System.Int32”类型的对象转换为“System.String”类型

我在这里错过了什么?

【问题讨论】:

你遇到了什么异常??尝试使用Convert.ToString(value) 而不是value.ToString() 无法将“System.Int32”类型的对象转换为“System.String”类型。 我改成了dr.GetString(1).ToString(),但是错误还是一样。 显然,数据读取器的索引为 1 的列有一个值,其类型是 System.Int32,而不是 System.String 为什么只选择所有列,而您只阅读其中的一个?只需选择您想要的列 - 这将减少出错的可能性。 【参考方案1】:

您的列的类型不是string。显然是int。所以使用:

dr.getInt32(1).ToString()

甚至

dr.GetValue(1).ToString()

在数据库中键入更改应该更健壮。

作为某种一般性建议,我至少会尝试遵循:

只选择您需要的。这主要是出于性能原因您必须明确说明列名的原因,因此如果您不兼容地更改架构,至少会出现一个明显的错误。

使用名称访问字段,例如

dr.GetGuid(dr.GetOrdinal("id"))

这样的事情也可以通过扩展方法很好的解决:

public T GetFieldValue<T>(this DbDataReader reader, string columnName)

    return reader.GetFieldValue<T>(reader.GetOrdinal(columnName));


旁注:包括堆栈跟踪(或至少说明异常来自代码中的哪一行)可能有助于其他试图帮助您的人。正如您从疯狂的猜测中看到的那样,罪魁祸首可能是什么。我的猜测是堆栈跟踪看起来有点像这样:

SqlDataReader.GetString
YourCode.YourMethod

GetString 看起来或多或少像这样:

public string GetString(int index)

    return (string) GetValue(index);

【讨论】:

@AndreasNiedermair 是的,它是从零开始的。这就是为什么当你说GetString(1) 时,它会在他的表格的第二列中搜索。 是的,第一列是ID,第二列是nvarchar中的CategoryName 异常在这一行,我检查了。 "字符串名称 = dr.GetString(1);" 当您谈论健壮性时,您还应该考虑使用reader.IsDBNull(int ordinal)-check 在使用序号访问它之前! ... ;) 然而,如此小的提示将大大减少陷阱,OP 可能不得不处理...【参考方案2】:

您的专栏似乎没有 int 类型。 为了避免这样的事情,您可以使用列名而不是索引。

try

    SqlCeCommand com = new SqlCeCommand("select * from Category_Master", con);
    SqlCeDataReader dr = com.ExecuteReader();
    while(dr.Read())
        string name = dr["yourColumnName"].ToString();
        cmbProductCategory.Items.Add(name);
    

catch(Exception ex)

    System.Windows.Forms.MessageBox.Show(ex.Message, System.Windows.Forms.Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);

【讨论】:

那不是正当理由!!使用序数,您可以执行键入的操作,例如 GetStringGetInt32... 使用字符串索引器,您可以访问 object(未键入)值 正确,但至少您可以确定要处理的是哪一列。 仍然没有正当理由...reader.GetOrdinal("myColumn") 给出了我要处理的列的序号 - 你怎么能更明确?! @AndreasNiedermair 点了。【参考方案3】:

好的好的。解决了……

这是代码..

        try
        
            SqlCeCommand com = new SqlCeCommand("select CategoryName from Category_Master", con);
            SqlCeDataReader dr = com.ExecuteReader();
            while(dr.Read())
                string name = dr.GetString(0);
                cmbProductCategory.Items.Add(name);
            
        
        catch(Exception ex)
        
            System.Windows.Forms.MessageBox.Show(ex.Message, System.Windows.Forms.Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);
        

我将 sqlcommand 更改为单个值,并将 dr.getstring() 的列号更改为 0.. 它起作用了。谢谢你们的帮助。我期待更多,因为我的项目只完成了一半。

【讨论】:

【参考方案4】:

在查询中使用列名,然后在阅读器中指定该列名。

SqlCeCommand com = new SqlCeCommand("select catg from Category_Master", con);
                SqlCeDataReader dr = com.ExecuteReader();
                while(dr.Read())
                    string name = dr("catg").ToString();
                    cmbProductCategory.Items.Add(name);
                

【讨论】:

【参考方案5】:

您可以尝试以下转换:

  Convert.ToInt32(yourstring)

【讨论】:

以上是关于无法在 DataReader.GetString() 中将“System.Int32”类型的对象转换为“System.String”类型的主要内容,如果未能解决你的问题,请参考以下文章

项目中遇到的扩展方法-总结和分享

在NTFS分区上加密的文件夹在重装后无法访问(无法去掉加密)

包无法在 R 中卸载:无法安装包

无法在 SQL Server 视图中使用工作查询:“IS”无法识别“>”无法识别

无法在春季导入 org.apache.poi,因此无法编译

无法理解为啥计算在没有手表的情况下无法工作