Выпадающий список и Datareader

Попробовав множество решений, перечисленных в Интернете, я сейчас очень запутался. У меня есть веб-приложение C # / SQL, для которого я просто пытаюсь привязать команду ExecuteReader к раскрывающемуся списку, чтобы пользователь мог выбрать значение. Это проект VS2008 для ОС XP.

Как это работает, после того, как пользователь выберет таблицу, я использую этот выбор в качестве входного параметра для метода из моего файла Datamatch.aspx.cs. Затем этот файл Datamatch.aspx.cs вызывает метод из моего файла класса ADONET.cs. Наконец, этот метод выполняет процедуру SQL для возврата списка столбцов из этой таблицы. (Это все таблицы в БД Adventureworks). Я знаю, что этот метод успешно возвращает список столбцов, если я выполняю этот SP в SSMS. Однако я не уверен, как определить, работает ли он в VS или нет.

Это должно быть просто. Как я могу это сделать? Вот часть моего кода. Сохраненная процедура T-sQL:

CREATE PROCEDURE [dbo].[getColumnNames]
@TableName VarChar(50) AS
BEGIN
SET NOCOUNT ON;
SELECT col.name 'COLUMN_NAME' FROM sysobjects obj
INNER JOIN syscolumns col ON obj.id = col.id
WHERE obj.name = @TableName
END

Это дает мне желаемый результат, когда я выполняю следующее из SSMS: exec getColumnNames 'AddressType'

А код из файла Datamatch.aspx.cs в настоящее время:

закрытый void CreateDropDownLists () {SqlDataReader dr2 = ADONET_methods.DisplayTableColumns (targettable);

int NumControls = targettable.Length;
DropDownList ddl = new DropDownList();
DataTable dt = new DataTable();

dt.Load(dr2);

ddl.DataValueField = "id";
ddl.DataTextField = "text";
ddl.DataSource = dt;
ddl.DataBind();

for (int counter = 0; counter < NumberOfControls; counter++)
{
    ddl.ID = "DropDownListID " + (counter + 1).ToString();
    btnSubmit.Style.Add("top", "auto");
    btnSubmit.Style.Add("left", "auto");
    btnSubmit.Style.Add("position", "absolute");

    if (counter < 7)
    {
        ddl.Style["top"] = 100 * counter + 80 + "px";
        ddl.Style["left"] = 250 + "px";
        int bSubmitPosition = NumberOfControls * 100 + 80;
        btnSubmit.Style.Add("top", System.Convert.ToString(bSubmitPosition) + "px");
    }
    else if (counter >= 7)
    {
        ddl.Style["top"] = 100 * counter - 620 + "px";
        ddl.Style["left"] = 550 + "px";
        int bSubmitPosition = NumberOfControls * 100 - 620;
        btnSubmit.Style.Add("top", System.Convert.ToString(bSubmitPosition) + "px");
    }
    ddl.SelectedIndexChanged += new EventHandler(SelectedIndexChanged);
    ddl_ht.Add(counter, ddl.SelectedValue);

    pnlDisplayData.Controls.Add(ddl);
    pnlDisplayData.Controls.Add(new LiteralControl("<br><br><br>"));
    pnlDisplayData.Visible = true;
    pnlDisplayData.FindControl(ddl.ID);
    //  dr.Close();
}

}

private void CreateLabels () {для (int counter = 0; counter ‹NumberOfControls; counter ++) {Label lbl = new Label (); lbl.ID = "Метка" + counter.ToString (); lbl.Text = заголовки [счетчик]; lbl.Style ["позиция"] = "абсолютный"; if (counter ‹7) {lbl.Style [" верх "] = 100 * counter + 50 +" px "; lbl.Style ["left"] = 250 + "px"; } else if (counter> = 7) {lbl.Style ["top"] = (100 * counter) - 650 + "px"; lbl.Style ["left"] = 550 + "px"; }

    pnlDisplayData.Controls.Add(lbl);
    pnlDisplayData.Controls.Add(new LiteralControl("<br><br><br>"));
}

}

Где ADONET_methods.DisplayTableColumns (targettable):

public static SqlDataReader DisplayTableColumns(string tt)
    {
        SqlDataReader dr = null;
        string TableName = tt;
        string connString = "Server=(local);Database=AdventureWorks;Integrated Security = SSPI";
        string errorMsg;
        SqlConnection conn2 = new SqlConnection(connString);
        SqlCommand cmd = new SqlCommand("getColumnNames");  //conn2.CreateCommand();

        try
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Connection = conn2;
            SqlParameter parm = new SqlParameter("@TableName", SqlDbType.VarChar);
            parm.Value = "Person." + TableName.Trim();
            parm.Direction = ParameterDirection.Input;
            cmd.Parameters.Add(parm);
            conn2.Open();
            dr = cmd.ExecuteReader();

        }
        catch (Exception ex)
        {
            errorMsg = ex.Message;
        }
        return dr;
    }

Приведенный выше метод CreateLabels правильно показывает мне метки. Но метод CreateDropDownLists просто показывает мне один раскрывающийся список, в котором ничего нет. Другими словами, его нельзя выбрать. Итак, как я могу убедиться, что средство чтения данных возвращает все 4 столбца и проверить их значения? Мне удалось найти в хранилище данных "COLUMN_NAME", но я не знаю, в каких свойствах искать, чтобы проверить имена столбцов.


person salvationishere    schedule 08.04.2010    source источник
comment
Есть ли в какой-то момент сообщение об ошибке?   -  person Patrick Karcher    schedule 09.04.2010
comment
Просто к сведению, SqlDataReaders являются IDisposable и действительно действительно не должны покидать область, в которой они были созданы, особенно для заполнения раскрывающегося списка. Вам нужно просто прочитать все данные в коллекции в памяти и вернуть их.   -  person R0MANARMY    schedule 09.04.2010
comment
Ошибок нет. Но сейчас отображается только один раскрывающийся список, и он пуст! Romanarmy, не могли бы вы подробнее рассказать, как это сделать? Я обновляю свой вопрос выше своей последней попыткой.   -  person salvationishere    schedule 09.04.2010


Ответы (2)


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

ddl.DataTextField = "COLUMN_NAME";
ddl.DataValueField = "COLUMN_NAME";
ddl.DataSource = dr.ExecuteReader();
ddl.DataBind();

В качестве альтернативы вы можете сделать все это в разметке своей страницы с помощью элемента управления SqlDataSource.

  <asp:SqlDataSource
      id="SqlDataSource1"
      runat="server"
      DataSourceMode="DataSet"
      ConnectionString="myConnString"
      SelectCommand="myStoredProcedure"
      >
  </asp:SqlDataSource>

  <asp:MyDropDownList id="ddl" runat="server" DataSource="SqlDataSource1"
       DataTextField="COLUMN_NAME" DataValueField="COLUMN_NAME" />
person womp    schedule 08.04.2010
comment
Ознакомьтесь с моим отредактированным вопросом выше сейчас. Спасибо за советы! - person salvationishere; 09.04.2010

В методе ADONET_methods.DisplayTableColumns (targettable) перед возвратом dr проверьте, получили ли вы какое-либо значение для dr.GetValue () с помощью точки останова

string temp;
while(dr.Read())
{
    temp = dr.GetValue();  //use a breakpoint here
}

Кроме того, вместо использования dataReader и загрузки его в dataTable вы можете лучше использовать dataAdapter для непосредственного заполнения dataTable

public static DataTable DisplayTableColumns(string tt) 
{ 
    Datatable dt = new DataTable();
    SqlDataAdapter da = new SqlDataAdapter();

    try 
    { 
        da.Fill(dt); 
    } 
    catch (Exception ex) 
    { 
        errorMsg = ex.Message; 
    } 

    string temp;
    foreach(DataRow row in dt.Rows)
    {
        foreach(DataColumn column in dt.Columns)
        {
            temp = (row[column]);  // use your breakpoint here
        }
    }

    return dt; 
} 
person Amsakanna    schedule 09.04.2010
comment
Спасибо, ребята, за вашу помощь! Но я обнаружил, что настоящая проблема заключалась в том, что я давал этой хранимой процедуре SQL неправильное входное значение: Person.AddressType вместо AddressType. Я исправил это сейчас, и теперь это работает правильно! - person salvationishere; 09.04.2010
comment
@salvationishere: это решение по-прежнему является улучшением по сравнению с возвратом необработанного DataReader. Если это вообще возможно, попробуйте использовать Linq to SQL. - person R0MANARMY; 10.04.2010