2011-01-09 1 views
0

Я работаю над пониманием того, как связывать хранимые процедуры с приложениями. Мой пример прост, но он не отображает мои столбцы и строки в командной строке, вместо этого он отображает System.Data.SqlClient.SqlDataReader. Как отображать строки из моего сохраненного запроса?Программирование баз данных на C#, возвращающий результат из Stored Proc

----Stored Proc-- 

ALTER PROCEDURE dbo.SelectID 
AS 
SELECT * FROM tb_User; 
----- 

Ниже приведен код:

using System; 
using System.Data.SqlClient; 
using System.IO; 


namespace ExecuteStoredProc 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      SqlConnection cnnUserMan; 
      SqlCommand cmmUser; 
      //SqlDataReader drdUser; 

      //Instantiate and open the connection 
      cnnUserMan = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=c:\\Program Files\\Microsoft SQL Server\\MSSQL10.SQLEXPRESS\\MSSQL\\DATA\\UserDB.mdf; Integrated Security=True;Connect Timeout=30;User Instance=True"); 
      cnnUserMan.Open(); 

      //Instantiate and initialize command 
      cmmUser = new SqlCommand("SelectID", cnnUserMan); 
      cmmUser.CommandType = System.Data.CommandType.StoredProcedure; 

      //drdUser = cmmUser.ExecuteReader(); 
      Console.WriteLine(cmmUser.ExecuteReader()); 
      Console.ReadLine(); 
     } 
    } 
} 

Спасибо.

ответ

3

cmmUser. ExecuteReader() выполняет хранимую процедуру и возвращает объект SqlDataReader. Таким образом, вы должны использовать SqlDataReader, что вы закомментированы так:

SqlDataReader drdUser; 

drdUser = cmmUser.ExecuteReader(); 
while(drdUser.Read()){ 
    //You can get at each column in the row by indexing the reader using either the column number 
    // like drdUser[0] or the column name drdUser["COlumnName"]. Since I don't know the names of your 
    // columns I will use numbers 
    Console.WriteLine(String.Format("{0} {1} {2}", drdUser[0], drdUser[1], drdUser[2]); 
} 
drdUser.Close(): 

Кроме того, я рекомендовал бы обернув экземпляр вашего SqlConnection в использовании блока так, что она будет расположена, как только вы сделали с ним, как это:

namespace ExecuteStoredProc 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     {  
      //Instantiate and open the connection 
      using(SqlConnection cnnUserMan = new SqlConnection("Your connection string")) 
      { 
       cnnUserMan.Open(); 

       //Instantiate and initialize command 
       using(SqlCommand cmmUser = new SqlCommand("SelectID", cnnUserMan)) 
       { 
        cmmUser.CommandType = System.Data.CommandType.StoredProcedure; 

        using(SqlDataReader drdUser = cmmUser.ExecuteReader()) 
        {      
         while(drdUser.Read()) 
         { 
          Console.WriteLine(String.Format("{0} {1} {2}", drdUser[0], drdUser[1], drdUser[2]); 
         } 
        } 
       } 
       Console.ReadLine(); 
      } 
     } 
    } 
} 

UPDATE

согласно комментарий marc_s, это имеет смысл, чтобы обернуть все одноразовые компоненты, SqlConnection, SqlCommand и SqlDataReader в использовании блока, чтобы убедиться, они утилизируются должным образом, а не мое исходное решение, которое ТОЛЬКО завернуло SqlConnection с использованием блока.

UPDATE 2

Согласно комментарию по Торарин он выглядит чище, чтобы объявить переменную как часть с помощью блока, особенно в этом случае, если вам не нужен переменные вне каждый из блока с помощью ,

+0

отлично, что вы используете блок 'using() .....' для SqlConnection, но почему бы не использовать 'SqlCommand' и' SqlDataReader' тоже? Было бы рекомендуемой лучшей практикой, действительно .... –

+1

@marc_s вы абсолютно правы. Я должен был обернуть их все, используя блоки. Я обновил свой первоначальный ответ. Продолжайте замечательный обзор кода :) –

+0

Спасибо, я довольно новичок в интерфейсе C# с базами данных и нашел целый учебник по основам www.csharp-station.com/Tutorial.aspx. Если кто-либо еще прочтет это и станет новым для этой концепции и практики, я бы настоятельно предложил запустить учебники. – jpavlov

0

Вы не можете использовать Console.WriteLine для отображения DataTable, для этого вам нужно сканировать каждую строку таблицы с помощью циклов Foreach/for и печатать один за другим.

0

Вам нужно будет вручную генерировать выходную строку путем итерации DataReader, возвращаемой методом ExecuteReader, и построения столбца вывода по столбцу и по строке. Вы можете создать общий класс, чтобы сделать это для любого выхода datareader.

1

Этот код покажет все строки, возвращаемые хранимой процедуры:

static void Main(string[] args) 
{ 
    // Instantiate the connection 
    using (SqlConnection cnnUserMan = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=c:\\Program Files\\Microsoft SQL Server\\MSSQL10.SQLEXPRESS\\MSSQL\\DATA\\UserDB.mdf; Integrated Security=True;Connect Timeout=30;User Instance=True")) 
    using (SqlCommand cmmUser = cnnUserMan.CreateCommand()) 
    { 
     // Initialize command 
     cmmUser.CommandText = "SelectID"; 
     cmmUser.CommandType = CommandType.StoredProcedure; 

     cnnUserMan.Open(); 

     using (SqlDataReader dr = cmmUser.ExecuteReader()) 
     { 
      // Loop through returned rows 
      while (dr.Read()) 
      { 
       // Loop through all the returned columns 
       // Printing column name and value 
       for (int col = 0; col < dr.FieldCount; col++) 
       { 
        Console.WriteLine(dr.GetName(col) + " = " + dr.GetValue(col)); 
       } 
       Console.WriteLine(); 
      } 
     } 
    } 

    Console.ReadLine(); 
} 

Есть несколько изменений, которые я сделал. Вы можете заметить использование инструкции using, которая гарантирует, что объекты SqlConnection и SqlDataReader должным образом расположены. Это освободит соединение с базой данных, как только вы закончите.

Существует несколько способов прочитать вашу информацию, поэтому проверьте SqlDataReader documentation on MSDN. Кроме того, вы можете использовать более общий интерфейс IDataReader.

UPDATE:
Добавлено using заявление для SqlCommand а также, что в настоящее время экземпляр с CreateCommand вместо этого. Теперь команда создается до открытия соединения.

+1

отлично, что вы используете блок 'using() .....' для 'SqlConnection' и' SqlDataReader' - но почему бы и не для 'SqlCommand' тоже? –

+0

Спасибо Thorarin за то, что вы нашли время ответить на мой вопрос. Я очень ценю это. – jpavlov

+1

@marc_s: Теоретически вы правы в том, что 'SqlCommand' реализует' IDisposable', и поэтому он должен использоваться. В этом конкретном случае реализация фактически не делает ничего из следствия, но, конечно, лучше не делать таких предположений. Я изменю код. – Thorarin

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