【问题标题】:Am I using LINQ correctly to apply a variable amount of filters?我是否正确使用 LINQ 来应用可变数量的过滤器?
【发布时间】:2012-08-14 14:29:12
【问题描述】:

我在我的 .aspx 页面中填充了一个 DataGrid,并在页面上有一些下拉菜单用于过滤出现在网格中的数据。我正在尝试使用 LINQ 过滤我在 page_load 和下拉菜单的 SelecedIndexChanged 事件上绑定的 DataTable 中的数据。

这是我目前的方法:

Dim filteredData As DataTable = (From d In rawDataTable
                            Select d).CopyToDataTable

        If Me.cbFilter1.SelectedIndex > 0 Then

            filteredData = (From f In filteredData
                            Where f.Field(Of Date)("ADateField").Year = Me.cbFilter1.SelectedValue
                            Select f).CopyToDataTable

        End If

        If Me.cbFilter2.SelectedIndex > 0 Then

            filteredData = (From f In filteredData
                            Where f.Field(Of String)("AStringField") = Me.cbFilter2.SelectedValue
                            Select f).CopyToDataTable

        End If

        If Me.cbFilter3.SelectedIndex > 0 Then

            filteredData = (From f In filteredData
                            Where f.Field(Of Boolean)("ABooleanField") = (cbFilter3.SelectedValue = "Yes")
                            Select f).CopyToDataTable

        End If

        ' ...and finally binding my grid to filteredData

有没有更清洁和更有效的方法来做到这一点?你会怎么做? 谢谢!

【问题讨论】:

  • 不确定我的标题是否正确地描述了我在这里问的内容

标签: asp.net vb.net linq


【解决方案1】:

试试看。

filteredData = (From f In filteredData
     Where ((Me.cbFilter1.SelectedIndex > 0 And f.Field(Of Date)("ADateField").Year = Me.cbFilter1.SelectedValue) Or _
(Me.cbFilter2.SelectedIndex > 0 And f.Field(Of String)("AStringField") = Me.cbFilter2.SelectedValue))
     Select f).CopyToDataTable

【讨论】:

    【解决方案2】:

    为什么每次都执行CopyToDataTable?我会根据原始数据构造查询并在最后执行此步骤。

    Dim query = From d In rawDataTable Select d
    
    If Me.cbFilter1.SelectedIndex > 0 Then
        query = query.Where(Function(f) f.Field(Of Date)("ADateField").Year = Me.cbFilter1.SelectedValue)
    End If
    
    If Me.cbFilter2.SelectedIndex > 0 Then
        query = query.Where(Function(f) f.Field(Of String)("AStringField") = Me.cbFilter2.SelectedValue)
    End If
    
    If Me.cbFilter3.SelectedIndex > 0 Then
        query = query.Where(Function(f) f.Field(Of Boolean)("ABooleanField") = (cbFilter3.SelectedValue = "Yes"))
    End If
    
    Dim filteredData As DataTable = query.CopyToDataTable
    

    注意:像这样组合不同的 where 子句是完全合法的。结果与用“And”连接条件相同。

    【讨论】:

    • 不错。这就是我一直在寻找的
    【解决方案3】:

    您想要使用的是IQueryable 接口来处理添加多个where 子句。 IQueryable 允许您将 Where 子句链接到您的查询,同时推迟查询的执行,直到您为结果做好准备。您概述的方式多次执行查询。除此之外,您每次都调用.CopyToDataTable 方法,这可能会产生一些额外的性能影响。

    除了您可能应该完全摆脱 DataSets 和 DataTables 之外,这里有一个示例可以帮助您将它们与 IQueryable 一起使用:

        ' Calling the AsQueryable extension method starts your query off as an IQueryable '
        Dim query = (From d In rawDataTable
                     Select d).AsQueryable()
    
        If Me.cbFilter1.SelectedIndex > 0 Then
            query = query.Where(Function(f) f.Field(Of Date)("ADateField") = Me.cbFilter1.SelectedValue)
        End If
    
        If Me.cbFilter2.SelectedIndex > 0 Then
            query = query.Where(Function(f) f.Field(Of String)("AStringField") = Me.cbFilter2.SelectedValue)
        End If
    
        If Me.cbFilter3.SelectedIndex > 0 Then
            query = query.Where(Function(f) f.Field(Of Boolean)("ABooleanField") = (cbFilter3.SelectedValue = "Yes"))
        End If
    
        ' At this point, you shouldn't even need the .CopyToDataTable() method. '
        MyGrid.DataSource = query
        MyGrid.DataBind()
    

    【讨论】:

    • 太棒了!感谢您的见解
    【解决方案4】:

    在 DataTable 上使用 DataView 而不是 LINQ -> http://msdn.microsoft.com/en-us/library/system.data.datatable.defaultview.aspx

    filteredData.DefaultView.RowFilter = "AStringField = " & Me.cbFilter2.SelectedValue

    filteredData.DefaultView.RowFilter = "ADateField.Year = " & Me.cbFilter1.SelectedValue

    等等。等等

    所以你不用创建新的数据表而是过滤它。

    【讨论】:

      猜你喜欢
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-15
      • 1970-01-01
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多