Laden...

WebForms, SQLDataSource, SelectParameters, ALLE(*)

Erstellt von UltraEdit vor 6 Jahren Letzter Beitrag vor 6 Jahren 1.507 Views
U
UltraEdit Themenstarter:in
57 Beiträge seit 2013
vor 6 Jahren
WebForms, SQLDataSource, SelectParameters, ALLE(*)

Hallo Zusammen,

ich spiele mit WebForms2.0 mit MySQL-Datenbanken und SQLDataSource-Komponenten.

Ich habe einen ArtikelView(mit Gruppen(+id), Herstellern(+id), Einheiten(+id), usw...) erstellt.

Im Kopf der Page gibt es Comboboxen(ALLE Gruppen, ALLE Hersteller, Alle Einheiten, Artikel(TextBox), usw.)

  • Ich möchte nun nach den "eingestellten Parametern" (aus dem Pagekopf) die entsprechenden Artikel suchen...

  • Es soll aber auch möglich sein zB. aus ALLEN Gruppen, oder ALLEN Herstellen einen ArtikelNamen zu suchen...

  • Oder aus der Gruppe "Toppings" ALLE Kiwi-Toppings ALLER Hersteller zu suchen.
    (Also eine "*" Suche)

Ich habe folgenden Code gebaut:


    <asp:SqlDataSource ID="SqlDS_Artikel" runat="server"
        ConnectionString="<%$ ConnectionStrings:DB_Con %>"
        ProviderName="<%$ ConnectionStrings: DB_Con.ProviderName %>"
        SelectCommand="SELECT * FROM artikelpreise WHERE Gruppen_ID like ? AND Hersteller_ID like ?">

        <SelectParameters>
            <asp:ControlParameter ControlID="DDL_Gruppe" Name="Gruppen_ID" PropertyName="SelectedValue" Type="String" />
            <asp:ControlParameter ControlID="DDL_Hersteller" Name="Hersteller_ID" PropertyName="SelectedValue" Type="String" />
        </SelectParameters>
    </asp:SqlDataSource>

Im "Codebehind" füge ich folgenden Code hinzu(um die "ALLE" Funktion zu bauen:


    protected void DDL_Gruppe_DataBound(object sender, EventArgs e)
    {
        DDL_Gruppe.Items.Insert(0, new ListItem("ALLE(*)", "%"));
    }

    protected void DDL_Hersteller_DataBound(object sender, EventArgs e)
    {
        DDL_Hersteller.Items.Insert(0, new ListItem("ALLE(*)", "%"));
    }

Die Frage nun:
Ist es richtig, dass ich die "SelectedValues" in einen String zwinge um diese mit einem "LIKE %" aus der DB zu holen?
Eigentlich sind die SelectedValues ja INT32 und ich frage sie ja per "=" ab.

Ich habe Sorgen, das das "like" böse Performance kostet.

Was ist der richtige Weg?
(Ich bitte um ein paar Tipps)

Vielen Dank im Voraus...
UltraEdit.

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

ich denke ich würde hier eher das SelectCommand im CodeBehind verhackstücken.
Da gäbe es dann 2 Möglichkeiten,

1.
eine Methode die den Command-Text zurückgibt und die Parameter setzt, und das dann an das SelectCommand binden also im Markup:

<asp:SqlDataSource ID="SqlDS_Artikel" runat="server"
        ConnectionString="<%$ ConnectionStrings:DB_Con %>"
        ProviderName="<%$ ConnectionStrings: DB_Con.ProviderName %>"
        SelectCommand="<%# BuildSelectCommand() %>" />

und im CodeBehind


public string BuildSelectCommand()
{
   string command = "SELECT * FROM artikelpreise"
    // hier anhand der ausgewählten DDL-Werte prüfen welche Parameter benötigt werden
    // diese der SqlDataSource hinzufügen und das
    // Command richtig zusammenbauen, dass es nur das Benötigte enthält
    if(...)
    {
        SqlDS_Artikel.Parameters.Add(...);

        command += ...;
    }
    return command;
} 

oder

2.
Das Selecting-Event der SqlDataSource abonnnieren.
In den EventArgs steckt das DbCommand, das abgesetzt werden soll, dadrin hast Du auf den CommandText und die Parameters ebenfalls Zugriff und kannst auf die gleiche Weise wie oben in der BuildSelectCommand-Methode das Command nach Deinen Wünschen abändern.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca

U
UltraEdit Themenstarter:in
57 Beiträge seit 2013
vor 6 Jahren

Hallo MarsStein und vielen Dank für die Hilfe...
Habe 2 Tage gebastelt um es hin zu kriegen.

Deine Methode 2 hab ich nun zum laufen bekommen 👍

(Methode 1 gefiel mir besser, hatte aber große Probleme es umzusetzen)
(man muss wohl im LoadPage alles immer neu BINDEN, was ich nicht verstanden habe und es immer wieder Abstürze gab)...
(Die SelectCommand="<%# BuildSelectCommand() %>" /> wurde nie aufgerufen...)

Deine Methode 2 habe ich wie folgt umgesetzt:
(Bitte schau auch mal drüber, dass ich es nicht total verrissen habe und riesen Sicherheitslücken gebaut habe) 8)

(Die BasisInitialisierung: Sonst rufen wohl die 3 "Auswahl-Komponenten" bei Veränderung KEIN "SqlDS_Artikel_Selecting()" auf)


    <asp:SqlDataSource
        ID="SqlDS_Artikel" runat="server"
        ConnectionString="<%$ ConnectionStrings:Con %>"
        ProviderName="<%$ ConnectionStrings:Con.ProviderName %>"
        SelectCommand="SELECT * FROM artikelpreise WHERE Gruppen_ID = ? AND Hersteller_ID = ? AND Bezeichnung like ?"
        OnSelecting="SqlDS_Artikel_Selecting">
        <SelectParameters>
            <asp:ControlParameter ControlID = "DDL_Gruppe" Name = "Gruppen_ID" PropertyName = "SelectedValue" Type = "Int32" />
            <asp:ControlParameter ControlID = "DDL_Hersteller" Name = "Hersteller_ID" PropertyName = "SelectedValue" Type = "Int32" />
            <asp:ControlParameter ControlID = "tb_Such_Name" Name = "Bezeichnung" PropertyName = "Text" Type = "String" />
        </SelectParameters>
    </asp:SqlDataSource>

(Der CodeBehind...)


    protected void DDL_Gruppe_DataBound(object sender, EventArgs e)
    {
        DDL_Gruppe.Items.Insert(0, new ListItem("ALLE(*)", "0"));
    }


    protected void DDL_Hersteller_DataBound(object sender, EventArgs e)
    {
        DDL_Hersteller.Items.Insert(0, new ListItem("ALLE(*)", "0"));
    }


    protected void SqlDS_Artikel_Selecting(object sender, SqlDataSourceSelectingEventArgs e)
    {
        e.Command.Parameters.Clear();

        string command = "SELECT * FROM artikelpreise";
        bool needAND = false;

        if (DDL_Gruppe.SelectedIndex > 0 || DDL_Hersteller.SelectedIndex > 0 || tb_Such_Name.Text.Length > 0)
        {
            command += " WHERE ";
        }

        if (DDL_Gruppe.SelectedIndex > 0)
        {
            DbParameter dbP = e.Command.CreateParameter();
            dbP.DbType = System.Data.DbType.Int32; dbP.ParameterName = "Gruppen_ID"; dbP.Value = DDL_Gruppe.SelectedValue;
            e.Command.Parameters.Add(dbP);
            if (needAND) command += " AND ";
            command += "Gruppen_ID = ?";
            needAND = true;
        }
        
        if (DDL_Hersteller.SelectedIndex > 0)
        {
            DbParameter dbP = e.Command.CreateParameter();
            dbP.DbType = System.Data.DbType.Int32; dbP.ParameterName = "Hersteller_ID"; dbP.Value = DDL_Hersteller.SelectedValue;
            e.Command.Parameters.Add(dbP);
            if (needAND) command += " AND ";
            command += "Hersteller_ID = ?";
            needAND = true;
        }

        if (tb_Such_Name.Text.Length > 0)
        {
            DbParameter dbP = e.Command.CreateParameter();
            dbP.DbType = System.Data.DbType.String; dbP.ParameterName = "Bezeichnung"; dbP.Value = "%" + tb_Such_Name.Text + "%";
            e.Command.Parameters.Add(dbP);
            if (needAND) command += " AND ";
            command += "Bezeichnung like ?";
            needAND = true;
        }

        e.Command.CommandText = command;
    }

  • Mach ich das "richtig" mit den "DbParametern?"
    Vielen Dank im Voraus für ein paar weitere Tipps

mfg UltraEdit

3.170 Beiträge seit 2006
vor 6 Jahren

Hallo,

das passt schon so mit den Parametern 👍

Wenn Du genau weisst, um was für einen konkreten Typen es sich bei dem DbCommand handelt, kannst Du es ggf. noch casten und dann die Funktionen des konkreten Typen nutzen (z.b. wenn es ein SqlCommand ist, kannst Du darauf casten und die Parameter dann mittels AddWithValue hinzufügen).

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca