Падащ списък и четец на данни

След като изпробвах много решения, изброени в интернет, сега съм много объркан. Имам C#/SQL уеб приложение, за което просто се опитвам да свържа команда ExecuteReader към падащ списък, така че потребителят да може да избере стойност. Това е VS2008 проект на XP OS.

Как работи, след като потребителят избере таблица, аз използвам тази селекция като входен параметър към метод от моя файл Datamatch.aspx.cs. Тогава този файл Datamatch.aspx.cs извиква метод от моя файл с клас ADONET.cs. Накрая този метод изпълнява SQL процедура, за да върне списъка с колони от тази таблица. (Това са всички таблици в Adventureworks DB). Знам, че този метод връща успешно списъка с колони, ако изпълня този 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 в момента е:

private 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() { for (int counter = 0; counter ‹ NumberOfControls; counter++) { Label lbl = new Label(); lbl.ID = "Етикет" + counter.ToString(); lbl.Текст = заглавия[брояч]; lbl.Style["position"] = "абсолютен"; if (брояч ‹ 7) { lbl.Style["top"] = 100 * брояч + 50 + "px"; lbl.Style["left"] = 250 + "px"; } else if (брояч >= 7) { lbl.Style["top"] = (100 * брояч) - 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 са IDsposable и наистина наистина не трябва да напускат обхвата, в който са създадени, особено да не попълват падащ списък. Трябва просто да прочетете всички данни в колекция в паметта и да върнете това.   -  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 към SQL. - person R0MANARMY; 10.04.2010