Невозможно привести объект типа "System.Object[]" к типу "System.String[]".

Я занимаюсь разработкой веб-приложения на 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: 

6 ответов

Решение

Хммм. Вы пытаетесь получить доступ к свойствам 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 добавит это для вас. Приведение (string) будет работать до тех пор, пока в ключе 0 есть строка (что является довольно нестандартным способом использования хеш-таблиц - у вас обычно будет какой-то описательный ключ), и если первый столбец в вашей таблице данных содержит строки.

Я рекомендую вам взглянуть на типизированные наборы данных и общие коллекции. Отсутствие их здесь делает ваш код несколько хрупким.

Вы не можете преобразовать массив объектов в массив строк, вы должны преобразовать каждый элемент в массиве, так как каждый элемент должен быть проверен, если он может быть приведен. Вы можете использовать Cast метод для этого:

SingleRow = dt.Rows[1].ItemArray.Cast<string>().ToArray();
string[] arr = Array.ConvertAll(dt.Rows[1].ItemArray, o => (string)o);

(вы также можете использовать Cast<T>().ToArray(), но этот подход работает на нескольких версиях фреймворка и с самого начала получает правильный размер массива, а не изменяет его размер)

Каждый элемент столбца имеет свой собственный тип, который может отличаться от String, поэтому, если вы хотите сохранить каждое значение строки в массиве, вы должны сделать это один за другим с циклом или с LINQ (я не проверял этот фрагмент, но должен делать свою работу):

(from columnVal in dt.Rows[1].ItemArray
select columnVal.ToString()).ToArray();

Вы можете использовать LINQ для этого:

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

Это преобразует каждый элемент массива в строку с помощью ToString() и возвращает пустую строку, если элемент является нулевым.

Как насчет этого: сделать string[] SingleRow в 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;
Другие вопросы по тегам