2010-06-06 2 views
3

Я разрабатываю приложение веб-сайта C# VS 2008/SQL Server. Я новичок в ASP.NET. Однако я получаю вышеуказанную ошибку в последней строке следующего кода. Можете ли вы дать мне совет, как это исправить? Это выполняется правильно, но я столкнулся с этой ошибкой после запуска.Невозможно применить объект типа 'System.Object []' для ввода 'System.String []'

Все, что я пытаюсь сделать, это сохранить элементы из второй строки «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: 

ответ

1

Хммм. Вы пытаетесь получить доступ к свойствам DataTable dt, но похоже, что вы можете ожидать, что эта таблица будет содержать результаты запроса AppendDataCT. Это не так. Также будьте осторожны с вашими обращениями к строкам: массивы на C# основаны на 0, а dt.Rows[1] выберет вторую строку в таблице.

В этом случае просмотрите документацию для DataRow.ItemArray. Этот метод возвращает массив объектов, а не массив строк. Даже если ваша строка содержит ничего, кроме строк, вы по-прежнему имеете дело с массивом объектов, и вам придется относиться к этому так. Вы можете бросить каждый индивидуальный элемент в строке на строку, если это правильный тип данных для этого столбца:

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

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

Рекомендую вам посмотреть typed datasets и generic collections. Отсутствие их здесь делает ваш код несколько хрупким.

+0

Мне понравился этот ответ, потому что он оказался простым. Но когда я попытался ввести содержимое внутри этого оператора foreach, у меня возникла ошибка компилятора: Использование неназначенной локальной переменной 'SingleRow' Мое утверждение: SingleRow [i] = dt.Rows [1] .ItemArray.ToString(); – salvationishere

+0

Трудно ответить вам, не имея лучшего понимания того, что вы пытаетесь выполнить. Тем не менее, вам нужно создать экземпляр объекта 'SingleRow', прежде чем вы сможете получить доступ к его свойствам. –

+0

Можете ли вы описать, что вы пытаетесь выполнить, в целом? Возможно, какой-нибудь псевдокод поможет. –

9

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

SingleRow = dt.Rows[1].ItemArray.Cast<string>().ToArray(); 
+0

Спасибо, я попытался это, но это дало мне ошибку компилятора. В этом контексте Cast не распознается. – salvationishere

+1

Этот код, я считаю, требует Linq, поэтому вам нужно использовать .net 3.5 или выше, и вам нужно обратиться к Linq и использовать System.Linq –

0

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

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

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

+0

Мне тоже нравится ваше решение, используя эту строку: SingleRow = dt.Rows [1] .ItemArray.Select (o => (o ?? (object) String.Emtpy) .ToString()). ToArray(); Но я получаю сообщение об ошибке: Ошибка 'object []' не содержит определения для 'Select' и не используется метод расширения 'Select', принимающий первый аргумент типа 'object []', может быть (вам не хватает директивы использования или ссылки на сборку?) \t ... – salvationishere

1

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

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

- это код C# или LINQ? – salvationishere

+0

Выражения запроса LINQ являются компонентами C# 3.0+. –

+0

Должен ли я включать любые специальные пространства имен для этого? – salvationishere

3
string[] arr = Array.ConvertAll(dt.Rows[1].ItemArray, o => (string)o); 

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

0

Как насчет: сделать string[] SingleRow в object[] SingleRow, который позволит линии

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

выполнить надлежащим образом. Впоследствии, когда вам нужно получить доступ к его значения как массив строк, брось или LINQ выбрать так:

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

Убедитесь, что добавить следующие usings:

using System.Linq; 
using System.Collections.Generic; 
+0

Я никогда раньше не использовал LINQ. Как я могу указать эту вторую строку? Я попробовал как objectArray.Select (c => c.ToString()). ToArray(); и SingleRow.Select <объект, строка> (c => c.ToString()). ToArray(); , но оба дали мне ошибки компилятора. – salvationishere

+0

Какая версия .NET вы используете? Эмм ... Я также забыл упомянуть, вы должны добавить с помощью System.Linq; используя System.Collections.Generic; – code4life

+0

- 3.5 SP1. Я добавил эти «использование» операторов, но я все еще получаю ошибку компилятора: Имя «objectArray» не существует в текущем контексте – salvationishere