2014-02-06 8 views
2

Я делаю вызов хранимой процедуры SQL, которая возвращает небольшую таблицу пользователей и их боссов. Я хотел бы сравнить эту информацию с переменной в другой части моего приложения, чтобы разрешить/запретить редактирование строки GridView. Для этого кажется, что метод GetValues вернет мне то, что мне нужно, и это весь набор данных, возвращаемый хранимой процедурой. Мой thikning заключается в том, что как только у меня будут данные в моем приложении, я могу загрузить этот набор данных в массив и пропустить его, чтобы сделать то, что мне нужно сделать.Stuck on SqlDataReader.GetValues ​​Метод

Проблема в этом. В моем коде ниже я получаю ошибку

Не удается неявно преобразовать тип «Int» на «объект»

Когда я смотрю на documentation на этом методе, возвращаемое значение является int.

Мой вопрос в том, что хранимая процедура содержит строковые данные (имена пользователей и боссов), почему GetValues mehtod возвращает int? Как мои фактические данные представлены как число И как я могу получить свои данные в массиве на основе строк?

Я искал множество примеров и информации в Интернете, это, по-видимому, общая проблема новых людей. Я просто не понимаю или получаю это, и я не продвигаюсь. Любая помощь очень ценится!

public Object[] GetDeptAppData() 
    { 
     Object[] myObject; 
     string sp_deptapp, sp_status, sp_supervisor; 

     //execute stored procedure to get data from database 
     SqlConnection sqlConnection = new SqlConnection("Data Source=MyServer;Initial Catalog=MyCatalog;Persist Security Info=True;User ID=MyUser;Password=MyPassword"); 
     SqlCommand cmd = new SqlCommand(); 
     SqlDataReader reader; 

     cmd.CommandText = "SP_Admin_DeptApp_Load"; 
     cmd.CommandType = CommandType.StoredProcedure; 

     cmd.Connection = sqlConnection; 
     sqlConnection.Open(); 
     reader = cmd.ExecuteReader(); 

     if (reader.HasRows == true) 
     { 
      //sp_deptapp = reader.GetValue(0).ToString(); 
      //sp_status = reader.GetValue(1).ToString(); 
      //sp_supervisor = reader.GetValue(2).ToString(); 

      myObject = reader.GetValues(myObject); 
     } 
     else 
     { 
      //nothing in reader, throw exception 
     } 
     sqlConnection.Close(); 

     return myObject; 
    } 

ответ

9

Ошибка вы столкнулись находится в этой линии:

myObject = reader.GetValues(myObject); 

myObject представляет собой массив объектов и метод GetValues возвращает целое число, содержащее счетчик, который помещается в массиве.Поэтому для того, чтобы решить вашу ошибку, вы можете изменить строку следующим образом:

var count = reader.GetValues(myObject); 

Кроме того, в вашем коде, вы только получить одну строку данных. Это, конечно, прекрасно, если вы ожидаете только одного ряда. Когда ожидая несколько строк, то, как правило, цикл по строкам, как это:

while (reader.Read()) 
{ 
    // Read row and add row to list 
} 

Для образца о том, как использовать SqlDataReader, посмотреть link.


Образец

Если вы хотите получить несколько строк и хранить данные, я предлагаю, чтобы добавить класс для хранения данных в строке (вы можете проверить типы данных, так что они совпадают с типами, что SP возвращается):

public class Data 
{ 
    public string DeptApp { get; set; } 
    public string Status { get; set; } // this might be another data type 
    public string Supervisor { get; set; } 
} 

Затем извлечь строки следующим образом:

public Data[] GetDeptAppData() 
{ 
    //execute stored procedure to get data from database 
    using (SqlConnection sqlConnection = new SqlConnection("Data Source=MyServer;Initial Catalog=MyCatalog;Persist Security Info=True;User ID=MyUser;Password=MyPassword")) 
    { 
     SqlCommand cmd = new SqlCommand(); 
     cmd.CommandText = "SP_Admin_DeptApp_Load"; 
     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.Connection = sqlConnection; 
     sqlConnection.Open(); 
     using (var reader = cmd.ExecuteReader()) 
     { 
      if (!reader.HasRows) 
      { 
       // throw exception 
      } 
      var lst = new List<Data>(); 
      while (reader.Read()) 
      { 
       var row = new Data(); 
       row.DeptApp = reader.GetString(0); 
       row.Status = reader.GetString(1); 
       row.Supervisor = reader.GetString(2); 
       lst.Add(row); 
      } 
      return lst.ToArray(); 
     } 
    } 
} 
+0

« myObject - это массив объектов »- так это нормально? Я думал, что myObject будет единственным объектом, содержащим результаты хранимой процедуры. «Метод GetValues ​​возвращает целое число, содержащее счет, помещенный в массив». - Значит, все, что он делает, что-то подсчитывает? Что это такое, и почему меня это волнует? Мне все равно, сколько строк я вернул данные из хранимой процедуры, я забочусь о фактических данных. Кажется, что var COUNT будет содержать только число, представляющее количество элементов в хранимой процедуре. – Rob

+0

@Rob: no, myObject объявлен как 'Object []', поэтому он представляет собой массив объектов. SqlDataReader используется для извлечения одной строки данных за другой. GetValues ​​хранит данные в параметре и возвращает количество полей, которые были прочитаны из текущей строки (!). Если вы хотите получить несколько строк, вам нужно добавить цикл. Я продолжу свой ответ. – Markus

+0

У меня был WHILE lopp, который раньше, но я не думал, что мне это нужно, потому что я ожидал, что GetValues ​​() вернет все мои данные одним большим выстрелом в myObject – Rob

3

GetValues возвращает int который «Число экземпляров объекта в массиве.», поэтому вы не можете назначить его myObject. Это загадочно. Это фактически означает (я считаю) количество значений столбцов, возвращаемых для текущей строки.

Понадобится:

int numColumnsRetrieved = reader.GetValues(myObject); 

или что-то подобное.

Ваших данных затем присутствуют внутри myObject, но только для текущей строки, в соответствии с Документами «Заполняет массив объектов со значениями столбцов текущей строки». Таким образом, вам все равно нужно перебирать, такие как:

var myObjectList = new List<object[]>(); // ... shudder ... 
while (reader.Read()) 
{ 
    var myObject[] = new object[reader.FieldCount]; 
    int instances = reader.GetValues(myObject); 
    myObjectList.Add(myObject); 
} 

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

var usersAndBosses = new List<Tuple<string, string>>(); 
while (reader.Read()) 
{ 
    string username = reader.GetString(0); // column index 0 
    string bossname = reader.GetString(1); // column index 1 
    usersAndBosses.Add(Tuple.Create(username, bossname)); 
} 

EDIT

Если вы хотите использовать ложное использование для возвращаемого значения от GetValues, вы можете сгладить таблицу строк в список строк:

var myStringList = new List<string>(); 
while (reader.Read()) 
{ 
    var myObject[] = new object[100]; 
    int colCount = reader.GetValues(myObject); 
    for (int i = 0; i < colCount; i++) 
    { 
     myStringList.Add((string)myObject[i]); 
    } 
} 
+0

Тот же вопрос, что и у другого человека, который ответил: «Почему мне нужно« подсчитывать экземпляры объекта в массиве »? Я забочусь о данных, а не о том, сколько их там. Число ничего не делает для меня. Мне нравится ваш второй блок, у меня есть аналогичная вещь в моем коде выше. Я могу идентифицировать, используя while (reader.read()) три уникальных столбца данных, используя reader.getValue (0) .ToString(), но тогда мне просто нужно было бы загрузить его в массив, а затем передать метода, использующего RETURN. – Rob

+1

Первый ответ: я бы избегал прохождения вокруг массивов объектов, C# - строго типизированный язык (даже Tuples - ленивое кодирование, хотя, по крайней мере, вы можете обеспечить проверку типов во время компиляции). –

+0

Второй ответ: Если вы, например, передаете массив объектов длиной 10, если бы было только 3 столбца, он скажет вам, что он помещает только 3 значения в массив длины 10. Я никогда не использовал его для использования , 'GetValues' не предназначен для дампа всех строк и столбцов, нет метода, поэтому вам нужно итерации с помощью' reader.Read() ' –

Смежные вопросы