2014-12-10 3 views
1

Извините, если это несколько элементарный вопрос ... .net newb здесь бросили в глубокий конец.Вывод результатов хранимой процедуры

Я создал хранимую процедуру, чтобы вернуть запись, которую я выполняю, как показано ниже. Когда я проверяю «r» с точкой останова в Express Studio Express, мои данные возвращаются правильно.

MyPage.aspx.cs

protected void Page_Load(object sender, EventArgs e) 
{ 

    var dd = dealerDetails(); 
} 

protected DataTable dealerDetails() 
{ 
    SqlConnection cn; 
    SqlCommand cmd; 

    using (cn = new SqlConnection(Settings.Server.ConnectionString)) 
    { 
     cn.Open(); 
     cmd = new SqlCommand("spMyStoredProcedure", cn); 
     cmd.CommandType = CommandType.StoredProcedure; 

     cmd.Parameters.Add("@strslug", SqlDbType.NVarChar, -1).Value = Page.Request.QueryString["_slug"]; 
     JJ.Diagnostics.Tracer.Trace(cmd); 
     try 
     { 
      IDataReader r = cmd.ExecuteReader(); 
      while (r.Read()) 
      { 
       ?????? 
      } 

      r.Close(); 
      return ?????; 

     } 
     catch (SqlException exSql) 
     { 
      // Make an event log entry of the exception 
      EventLogController.LogException(exSql); 
      throw; 
     } 
     catch (Exception ex) 
     { 
      // Make an event log entry of the exception 
      EventLogController.LogException(ex); 
      throw; 
     } 

    } 


} 

Когда я просто пытаюсь вернуть г, я получаю сообщение об ошибке:

Cannot inplicityly convert type 'System.Data.IDataReader' to 'System.Data.DataTable'. An explicity conversion exists (are you missing a cast?)

Я хотел бы быть в состоянии получить доступ к результатам из этой хранимой процедуры в MyPage.aspx. Я бы предположил, что смогу сделать это с помощью <%=dd.propname%>. Правильно ли я в этом или потребует каких-либо дополнительных шагов?

Пожалуйста, дайте мне знать, если я пропустил какую-либо важную информацию здесь.

+1

честный совет - тем более, что вы изучаете .net поэтому надеюсь, вам легче установить хорошую/плохую привычку. Попытайтесь использовать более описательные имена переменных - нет причин для минимизации C#. – decPL

ответ

2

Согласно вашему методу dealerDetails подпись - возвращаемое значение DataTable. Поэтому вы не можете вернуть DataReader, потому что он не является производным от DataTable.

Вам необходимо создать DataTable и его столбцы и заполнить таблицу при чтении из dataReader.

Что-то вроде этого

using(var r = cmd.ExecuteReader()) 
{ 
    var dt = new DataTable(); 
    dt.Columns.Add("Column1_Name", typeof(column1_Type)); 
    dt.Columns.Add("Column2_Name", typeof(column2_Type)); 

    while (r.Read()) 
    { 
     var dro = dt.NewRow(); 
     dro["Column1_Name"] = somevalue_from_reader; 
     dro["Column2_Name"] = somevalue_from_reader; 
     dt.Rows.Add(dro); 
    } 

    r.Close(); 
    return dt; 
} 
+0

Поскольку OP является новым для .NET, может оказаться полезным пройти дополнительную длину и показать ему директиву 'using'. – decPL

+1

@decPL Разумный комментарий, спасибо. Я обновил ответ. –

+1

@ AndyKorneyev Или просто сделайте 'dt.Load (r);' –

3

Используйте адаптер данных для заполнения таблицы данных и вернуть это. Если ваша хранимая процедура возвращает только данные, которые необходимы. Я не вижу причин перебирать каждый столбец и явно определять их. A SqlDataAdapter заполнит DataTable для вас без жесткого кодирования и добавления значений строк.

HERE - некоторые данные и примеры SqlDataAdapters.

using (SqlDataAdapter da = new SqlDataAdapter(cmd, cn) 
{ 
    DataTable dt = new DataTable("TableName"); 
    da.Fill(dt); 
    return dt; 
} 

Весь код:

// Utilize the using directive on any disposable objects so you aren't 
// left with garbage. 
using (SqlConnection cn = new SqlConnection(Settings.Server.ConnectionString)) 
using (SqlCommand cmd = new SqlCommand("spMyStoredProcedure", cn)) 
{ 
    cmd.CommandType = CommandType.StoredProcedure; 
    // define your parameter here, just personal preference, but makes debugging 
    //easier in my opinion. 
    string slug = Page.Request.QueryString["_slug"]; 
    // Use the newer .AddWithValue command. 
    cmd.Parameters.AddWithValue("@strslug", slug); 
    JJ.Diagnostics.Tracer.Trace(cmd); 

    try 
    { 
     // SqlDataAdapter will automatically open/close your connection for you, 
     // however, for future reference, try to open your connection only when 
     // it is required to be opened. This will reduce your connection time/ 
     // server strain. 
     // cn.Open(); 
     using (SqlDataAdapter da = new SqlDataAdapter(cmd, cn) 
     { 
      // Data adapter will automatically fill your returned data table. 
      DataTable dt = new DataTable("TableName"); 
      da.Fill(dt); 
      return dt; 
     } 
    } 
    catch (SqlException exSql) 
    { 
     // Make an event log entry of the exception 
     EventLogController.LogException(exSql); 
     throw; 
    } 
    catch (Exception ex) 
    { 
     // Make an event log entry of the exception 
     EventLogController.LogException(ex); 
     throw; 
    } 
} 

С этого момента вы можете получить доступ к данным, как это:

protected void Page_Load(object sender, EventArgs e) 
{ 
    DataTable dd = dealerDetails(); 
    // if more than one row is expected you can use the for loop 
    // if not, just access them directly. 
    for (int i = 0; i < d.Rows.Count - 1; i++) 
    { 
     // Jump straight to here if you are positive you will only 
     // return 1 row of data. 
     string ColumnName1 = dd.Rows[i]["ColumnName1"].ToString(); 
     string ColumnName2 = dd.Rows[i]["ColumnName2"].ToString(); 
    } 
} 
+0

что бы это сделать, кроме как идти против SOLID? – decPL

+0

@decPL Как именно это «идет ... против SOLID»? – Volearix

+1

* Необходимо «Зависить от абстракций. Не зависеть от конкреций ». * И даже если вы игнорируете это как руководство, а не правило (что, очевидно, верно), ваш ответ все еще не делает ничего, чтобы исправить проблему OP. – decPL

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