4

我正在开发一个 C# VS 2008 / SQL Server 网站应用程序。我是 ASP.NET 的新手。但是,在以下代码的最后一行,我收到了上述错误。你能给我建议如何解决这个问题吗?这编译正确,但运行后我遇到了这个错误。

我要做的就是将“dt”第二行中的项目存储到字符串参数中。第一行是标题,所以我不想要这些值。第二行是第一行值。我的 SQL 存储过程需要这些值作为字符串。所以我想解析第二行数据并加载到2个字符串参数中。我在下面添加了更多代码。

DataTable dt; 
Hashtable ht;
string[] SingleRow;
...
SqlConnection conn2 = new SqlConnection(connString);
SqlCommand cmd = conn2.CreateCommand();
cmd.CommandText = "dbo.AppendDataCT";
cmd.Connection = conn2;
SingleRow = (string[])dt.Rows[1].ItemArray;
            SqlParameter sqlParam = cmd.Parameters.AddWithValue("@" + ht[0], SingleRow[0]);
            sqlParam.SqlDbType = SqlDbType.VarChar;
            SqlParameter sqlParam2 = cmd.Parameters.AddWithValue("@" + ht[1], SingleRow[1]);
            sqlParam2.SqlDbType = SqlDbType.DateTime;

我的错误:

System.InvalidCastException was caught
  Message="Unable to cast object of type 'System.Object[]' to type 'System.String[]'."
  Source="App_Code.g68pyuml"
  StackTrace:
       at ADONET_namespace.ADONET_methods.AppendDataCT(DataTable dt, Hashtable ht) in c:\Documents and Settings\Admin\My Documents\Visual Studio 2008\WebSites\Jerry\App_Code\ADONET methods.cs:line 88
  InnerException: 
4

6 回答 6

11

您不能将对象数组转换为字符串数组,您必须转换数组中的每个项目,因为必须检查每个项目是否可以转换。您可以使用以下Cast方法:

SingleRow = dt.Rows[1].ItemArray.Cast<string>().ToArray();
于 2010-06-06T21:56:39.970 回答
3
string[] arr = Array.ConvertAll(dt.Rows[1].ItemArray, o => (string)o);

(您也可以使用Cast<T>().ToArray(),但这种方法适用于更多框架版本,并且从一开始就正确获取数组大小,而不是调整它的大小)

于 2010-06-06T22:08:36.617 回答
2

嗯。您正在尝试访问 DataTable 的属性dt,但看起来您可能希望该表包含AppendDataCT查询结果。它没有。也要小心你的行索引访问:C# 中的数组是从 0 开始的,并且dt.Rows[1]会检索表中的第二行。

除此之外,请查看DataRow.ItemArray的文档。该方法返回一个对象数组,而不是字符串数组。即使您的行只包含字符串,您仍然在处理一组对象,并且您必须以这种方式对待它。如果这是该列的正确数据类型,则可以将行中的每个单独项目转换为字符串:

foreach (string s in dt.Rows[1].ItemArray)
{
  //...
}

编辑:好的,作为对您的编辑的回应,我知道您要做什么。有很多不同的方法可以做到这一点,我特别建议你远离 HashTables 并转向像Dictionary这样的通用等价物- 你会为自己节省很多运行时铸造的痛苦。也就是说,这是您的代码最简单的改编:

DataRow dr = dt.Rows[1]; // second row
SqlParameter p1 = cmd.Parameters.AddWithValue((string)ht[0], (string)dr[0]);
SqlParameter p2 = ...

您不需要前导“@”;ADO.NET 将为您添加它。只要键 0 处有一个字符串(这是使用哈希表的一种相当非标准的方式——您通常会有某种描述性键),并且如果您的数据表中的第一列包含字符串。

我建议您查看类型化数据集通用集合。这里缺少它们会使您的代码有些脆弱。

于 2010-06-06T22:00:18.163 回答
1

每个列项都有自己的类型,可以与字符串不同,因此如果要将每个行值存储到数组中,则必须使用循环或 LINQ 逐个进行(我尚未测试这个片段,但应该做它的工作):

(from columnVal in dt.Rows[1].ItemArray
select columnVal.ToString()).ToArray();
于 2010-06-06T22:00:43.123 回答
0

您可以为此使用 LINQ:

var yourStringArray = dt.Rows[1].ItemArray
    .Select(o => (o ?? (object)String.Emtpy).ToString())
    .ToArray();

这将使用 ToString() 将数组的每个项目转换为字符串,如果项目为空,则返回一个空字符串。

于 2010-06-06T21:58:24.430 回答
0

这个怎么样: make string[] SingleRowinto object[] SingleRow,这将让行

SingleRow = (object[])dt.Rows[1].ItemArray;

正确执行。随后,当您需要将其值作为字符串数组访问时,将其强制转换或 LINQ 选择它,如下所示:

objectArray.Select<object, string>
   (c => (c != null ? c.ToString() : "")).ToArray();

确保添加以下用法:

using System.Linq;
using System.Collections.Generic;
于 2010-06-06T22:42:31.163 回答