SQL Server How to Bind data based on dropdownlists in repeater vb.net

gijlo24d  于 2023-05-16  发布在  .NET
关注(0)|答案(2)|浏览(93)

I have 5 Dropdownlist/Comboboxes. Is there a more efficient way to bind the data using a function and parameter where in some cases Parameter can be null. Instead of creating an individual databind for each scenario.

I want the user to be able to see the data in the repeater based on one or more (combinations) of dropdownlist selections. Eg. user selects value in DdlA and in ComboboxA but wants to leave the others blank.

below is a sample of code I have wrote which works for only one selection at a time. how can I tweak it to use multiple but not necessarily all selected values.

Protected Sub BttnSave_Click(sender As Object, e As EventArgs) Handles BttnSave.Click

       If DdlA.SelectedValue = "1" And DdlB.SelectedValue = "1" And DdlC.SelectedValue = "1" And ComboboxA.SelectedValue = "" And DdlD.Text = "" Then
        Me.ReadAllData()
    ElseIf DdlA.SelectedValue <> "1" And DdlB.SelectedValue = "1" And DdlC.SelectedValue = "1" And ComboboxA.SelectedValue = "" And DdlD.Text = "" Then
        Me.ReadAData()
    ElseIf DdlA.SelectedValue = "1" And DdlB.SelectedValue <> "1" And DdlC.SelectedValue = "1" And ComboboxA.SelectedValue = "" And DdlD.Text = "" Then
        ReadBData()
    ElseIf DdlA.SelectedValue = "1" And DdlB.SelectedValue = "1" And DdlC.SelectedValue <> "1" And ComboboxA.SelectedValue = "" And DdlD.Text = "" Then
        ReadCData()
    ElseIf DdlA.SelectedValue = "1" And DdlB.SelectedValue = "1" And DdlC.SelectedValue = "1" And ComboboxA.SelectedValue <> "" And DdlD.Text = "" Then
        ReadComboboxData()
    ElseIf DdlA.SelectedValue = "1" And DdlB.SelectedValue = "1" And DdlC.SelectedValue = "1" And ComboboxA.SelectedValue = "" And DdlD.Text <> "" Then
        ReadDData()
    End If
 End Sub

  Private Sub ReadAData()
    Dim query As String = "SELECT * FROM Test WHERE A = @A ORDER BY ID DESC"
    Dim cmd As SqlCommand = New SqlCommand(query)
    cmd.Parameters.AddWithValue("@A", DdlA.SelectedItem.Text)
    Using con As SqlConnection = New SqlConnection(GblSqlCon)
        Using sda As SqlDataAdapter = New SqlDataAdapter()
            cmd.Connection = con
            sda.SelectCommand = cmd
            Using dt As DataTable = New DataTable()
                sda.Fill(dt)
                Repeater1.DataSource = dt
                Repeater1.DataBind()
            End Using
        End Using
    End Using
End Sub

  Private Sub ReadBData()
    Dim query As String = "SELECT * FROM [dbo].[TestActivityLog] WHERE B = @B ORDER BY ID DESC"
    Dim cmd As SqlCommand = New SqlCommand(query)
    cmd.Parameters.AddWithValue("@B", DdlB.SelectedItem.Text)
    Using con As SqlConnection = New SqlConnection(GblSqlCon)
        Using sda As SqlDataAdapter = New SqlDataAdapter()
            cmd.Connection = con
            sda.SelectCommand = cmd
            Using dt As DataTable = New DataTable()
                sda.Fill(dt)
                Repeater1.DataSource = dt
                Repeater1.DataBind()
            End Using
        End Using
    End Using
End Sub
cld4siwp

cld4siwp1#

If you want all or "some" of the combo box to be optional for the search criteria , then you do NOT need to handle all combinations.

The simple way is to look at a combo box, if it has a value, then you filter, if the combo box is empty, then you ignore it.

This approach works for 3 or 15 optional filter box(s).

Sub Test()

    Dim strSQL As String =
        "SELECT * FROM TestActivityLog "

    Dim cmdSQL As New SqlCommand("")

    Dim strWhere = ""

    If DdlA.SelectedIndex > 0 Then
        strWhere = " (A = @A)"
        cmdSQL.Parameters.Add("@A", SqlDbType.Int).Value = DdlA.SelectedItem.Value
    End If

    If DdlB.SelectedIndex > 0 Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (B = @B)"
        cmdSQL.Parameters.Add("@B", SqlDbType.Int).Value = DdlB.SelectedItem.Value
    End If

    If DdlC.SelectedIndex > 0 Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (C = @C)"
        cmdSQL.Parameters.Add("@C", SqlDbType.Int).Value = DdlC.SelectedItem.Value
    End If

    If strWhere <> "" Then
        strSQL &= strWhere
    End If

    cmdSQL.CommandText = strSQL

    Using conn As New SqlConnection(My.Settings.TEST4)
        cmdSQL.Connection = conn
        Using (cmdSQL)
            conn.Open()

            Dim rstData = New DataTable
            rstData.Load(cmdSQL.ExecuteReader)
            Repeater1.DataSource = rstData
            Repeater1.DataBind()

        End Using
    End Using

End Sub

Many don't realize that the SQL command object allows adding as many parameters as you want, and the final SQL does NOT have to be defined WHILE you add these parameters.

So the design pattern is:

Check if control has value - if yes, then add to sql, and add to parameter.

Keep going until done.

As you can see, then you don't have to deal with all of the combinations of the filter options - you just ignore ones without a value.

I don't have your data, but lets do a proof of concept.

I have a list of hotels.

I want a filter for "active" ones.
I want a filter by City
I want a filter by Province (state)
I want a filter for only hotels with description
I want a filter for rooms with balcony
I want a filter for Water/Lake view

Now, recalling high school math (combinations and permutations), the above is 6! (6 factorial) and represents 720 combinations!!!

We can't possible code that out!!!

However, WE STILL want sql inject safe code (that means parameter).

So, we have this markup:

So, ALL of the filter options are "optional"

The code pattern thus is SAME as first example, and looks like this:

So, code to load combox (not really important - but a good FYI!!!)

Sub LoadCombos()

    Dim cmdSQL As New _
        SqlCommand("SELECT City FROM tblHotels WHERE City is not null GROUP by City")
    cboCity.DataSource = MyrstP(cmdSQL)
    cboCity.DataBind()
    cboCity.Items.Insert(0, New ListItem("Select", "0"))

    cmdSQL.CommandText =
        "SELECT Province FROM tblHotels WHERE Province is not null GROUP by Province"
    cboProvince.DataSource = MyrstP(cmdSQL)
    cboProvince.DataBind()
    cboProvince.Items.Insert(0, New ListItem("Select", "0"))

End Sub

So, the filter code is quite simple code, this:

Sub LoadByFilter()

    Dim strSQL As String = "SELECT * FROM tblHotels"
    Dim strOrderBy As String = " ORDER BY HotelName"
    Dim strWhere As String = ""

    Dim cmdSQL As New SqlCommand("")

    If cboCity.SelectedIndex > 0 Then
        strWhere = "(City = @City)"
        cmdSQL.Parameters.Add("@City", SqlDbType.NVarChar).Value = cboCity.SelectedItem.Text
    End If

    If cboProvince.SelectedIndex > 0 Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= "(Province = @Prov)"
        cmdSQL.Parameters.Add("@Prov", SqlDbType.NVarChar).Value = cboProvince.SelectedItem.Text
    End If

    ' must have description
    If chkDescripiton.Checked Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (Description is not null)"
    End If

    If chkActiveOnly.Checked Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (Active = 1)"
    End If

    If chkBalconyOnly.Checked Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (Balcony  = 1)"
    End If

    If chkWaterOnly.Checked Then
        If strWhere <> "" Then strWhere &= " AND "
        strWhere &= " (LakeView  = 1)"
    End If


    If strWhere <> "" Then
        strSQL &= " WHERE " & strWhere
    End If

    strSQL &= " " & strOrderBy
    cmdSQL.CommandText = strSQL

    Dim rstData As DataTable = MyrstP(cmdSQL)
    GridView1.DataSource = rstData
    GridView1.DataBind()

End Sub

In fact MUCH of the above is cut + paste over and over.

And now we see/get this:

pgccezyw

pgccezyw2#

EDITED
Try using StoredProcedures.
If I am not wrong you want to create something like if any combobox value is selected then your repeater should load up.

Check this following method.

  • IN VB.NET
Private Sub ReadAllData()

  'I Used oledbConnection, you can continue using sqlconnection.
  Using xcn As New OleDbConnection
      Using com As New OleDbCommand
          xcn.ConnectionString = "YOUR CONNECTION STRING"
          com.Connection = xcn
          com.CommandType = CommandType.StoredProcedure
          com.CommandText = "YOUR STORED PROCEDURE NAME"
          'try to pass string.empty or "" if your combobox value is null
          com.Parameters.AddWithValue("@A", OleDb.OleDbType.VarChar).Value = IIf(DdlA.SelectedValue = Nothing, "", DdlA.SelectedValue)
          com.Parameters.AddWithValue("@B", OleDb.OleDbType.VarChar).Value = IIf(DdlB.SelectedValue = Nothing, "", DdlB.SelectedValue)
          com.Parameters.AddWithValue("@C", OleDb.OleDbType.VarChar).Value = IIf(DdlC.SelectedValue = Nothing, "", DdlC.SelectedValue)
          com.Parameters.AddWithValue("@D", OleDb.OleDbType.VarChar).Value = IIf(DdlD.SelectedValue = Nothing, "", DdlD.SelectedValue)
          com.Parameters.AddWithValue("@E", OleDb.OleDbType.VarChar).Value = IIf(DdlE.SelectedValue = Nothing, "", DdlE.SelectedValue)
          xcn.Open()
          Using dt As DataTable = New DataTable()
              sda.Fill(dt)
              Repeater1.DataSource = dt
              Repeater1.DataBind()
          End Using
      End Using
  End Using
End Sub

To Create SQL Server Stored Procedure,

CREATE PROCEDURE [dbo].[YourProcedureName]  @A varchar(MAX), @B varchar(MAX), @C varchar(MAX), 
                                            @D varchar(MAX), @E varchar(MAX)
as
DECLARE @sql as varchar (MAX)
   set @sql = 'Select (All your column names except type1) from 
                (SELECT 1 as type1, * FROM [dbo].[TestActivityLog]) as A
               where A.type1 = 1'
    if @A <> ''
        begin
            set @sql = @sql + ' AND ColumnA IN ('+ @A +')'
        end
    if @B <> ''
        begin
            set @sql = @sql + ' AND ColumnB IN ('+ @B +')'
        end
    if @C <> ''
        begin
            set @sql = @sql + ' AND ColumnC IN ('+ @C +')'
        end
    if @D <> ''
        begin
            set @sql = @sql + ' AND ColumnD IN ('+ @D +')'
        end
    if @E <> ''
        begin
            set @sql = @sql + ' AND ColumnE IN ('+ @E +')'
        end
    set @sql = @sql + ' ORDER BY columnnames'
exec (@sql)

If you have a column with a fixed value in your table TestActivityLog then you can avoid type1 and use it something like this

set @sql = 'SELECT * FROM [dbo].[TestActivityLog] where FixedvalueColumn = thatfixedvalue' if... and continue code as above.

I hope this helps you. :)

相关问题