2010-04-08 13 views
2

Après avoir essayé de nombreuses solutions répertoriées sur Internet, je suis très confus maintenant. J'ai une application Web C#/SQL pour laquelle j'essaie simplement de lier une commande ExecuteReader à une liste déroulante afin que l'utilisateur puisse sélectionner une valeur. C'est un projet VS2008 sur un système d'exploitation XP.Dropdownlist et Datareader

Comment cela fonctionne est après que l'utilisateur sélectionne une table, j'utilise cette sélection comme un paramètre d'entrée à une méthode de mon fichier Datamatch.aspx.cs. Ensuite, ce fichier Datamatch.aspx.cs appelle une méthode de mon fichier de classe ADONET.cs. Enfin, cette méthode exécute une procédure SQL pour renvoyer la liste des colonnes de cette table. (Ce sont toutes des tables dans Adventureworks DB). Je sais que cette méthode renvoie avec succès la liste des colonnes si j'exécute ce SP dans SSMS. Cependant, je ne suis pas sûr de savoir si cela fonctionne en VS ou pas.

Cela devrait être simple. Comment puis-je faire ceci? Voici une partie de mon code. Le T-sql proc stocké:

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 

Il me donne la sortie désirée lorsque j'exécutons la suite de SSMS: exec getColumnNames 'AddressType'

Et le code de Datamatch.aspx.cs fichier est actuellement:

private void CreateDropDownLists() { SqlDataReader dr2 = ADONET_methods.DisplayTableColumns (cible);

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(); 
} 

}

CreateLabels private void() { for (int compteur = 0; compteur < NumberOfControls, contre ++) { label LBL = new label(); lbl.ID = "Label" + counter.ToString(); lbl.Text = en-têtes [compteur]; lbl.Style ["position"] = "absolute"; if (compteur < 7) { lbl.Style ["top"] = 100 * compteur + 50 + "px"; lbl.Style ["left"] = 250 + "px"; } sinon if (compteur> = 7) { lbl.Style ["top"] = (compteur 100 *) - 650 + "px"; lbl.Style ["left"] = 550 + "px"; }

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

}

Où ADONET_methods.DisplayTableColumns (targettable) est:

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; 
    } 

La méthode ci-dessus CreateLabels correctement me montre les étiquettes. Mais la méthode CreateDropDownLists me montre simplement une liste déroulante avec rien dedans. En d'autres termes, il n'est pas sélectionnable. Alors, comment puis-je vérifier que le lecteur de données retourne toutes les 4 colonnes et inspecte leurs valeurs? J'ai été en mesure de trouver à partir du lecteur de données "COLUMN_NAME" mais je ne sais pas quelles propriétés rechercher pour vérifier les noms des colonnes.

+0

Y at-il un message d'erreur à un moment donné? –

+0

Juste un FYI, ** SqlDataReaders ** sont IDisposable et vraiment ** vraiment ** ne devrait pas quitter la portée dans laquelle ils ont été créés, en particulier pour ne pas remplir une liste déroulante. Vous devriez juste lire toutes les données dans une collection de mémoire et renvoyer cela. – R0MANARMY

+0

Pas d'erreur. Mais il n'y a qu'une liste déroulante montrant maintenant et c'est vide! Romanarmy, pouvez-vous expliquer plus sur la façon de faire cela? Je suis en train de mettre à jour ma question ci-dessus avec ma dernière tentative. – salvationishere

Répondre

2

Il ne semble pas que vous liez réellement la liste déroulante n'importe où dans ce code. Vous devez faire quelque chose comme ceci:

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

Alternativement, vous pouvez faire tout cela dans votre balisage de la page en utilisant un contrôle 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" /> 
+0

Checkout ma question éditée ci-dessus maintenant. Merci pour vos conseils! – salvationishere

2

Dans la méthode ADONET_methods.DisplayTableColumns (__gVirt_NP_NN_NNPS<__) avant de retourner table cible dr, vérifier si vous obtenez une valeur pour dr.GetValue() à l'aide d'un point d'arrêt

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

également au lieu d'utiliser datareader et le charger à dataTable, vous pouvez mieux utiliser un dataAdapter pour remplir le dataTable directement

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; 
} 
+0

Merci les gars pour toutes vos aides! Mais j'ai trouvé que le vrai problème était que je donnais à cette procédure stockée SQL la mauvaise valeur d'entrée: "Person.AddressType" au lieu de "AddressType". J'ai réparé ceci maintenant et maintenant cela fonctionne correctement! – salvationishere

+0

@salvationishere: Cette solution constitue toujours une amélioration par rapport au retour d'un 'DataReader 'brut. Si du tout une option, vous devriez essayer d'utiliser Linq à SQL. – R0MANARMY