Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有Linq查询的VB.NET过滤_Vb.net_Linq - Fatal编程技术网

带有Linq查询的VB.NET过滤

带有Linq查询的VB.NET过滤,vb.net,linq,Vb.net,Linq,我的任务是向结果集中添加过滤机制。我理解在Linq中使用Where子句进行过滤的基本概念,但是必须有更好的方法来做到这一点,对吗 情景: 我的结果集中有5个可过滤列。我必须考虑这5个过滤器在任何给定时间的所有变化。这意味着我必须手动键入包含120种不同变体的If/ElseIf语句 这是事情发展的一般方式,我只需要问:有没有更好、更快的方式 过滤器 ByVal SearchMxMID As Integer, ByVal SearchProfile As Integer, ByVal SearchC

我的任务是向结果集中添加过滤机制。我理解在Linq中使用Where子句进行过滤的基本概念,但是必须有更好的方法来做到这一点,对吗

情景: 我的结果集中有5个可过滤列。我必须考虑这5个过滤器在任何给定时间的所有变化。这意味着我必须手动键入包含120种不同变体的If/ElseIf语句

这是事情发展的一般方式,我只需要问:有没有更好、更快的方式

过滤器

ByVal SearchMxMID As Integer,
ByVal SearchProfile As Integer,
ByVal SearchCZ As String,
ByVal SearchTerm As Integer,
ByVal SearchFwMth As Integer
If语句的过程

If SearchMxMID = 0 
And SearchProfile = 0 
And SearchCZ =    "All" 
And SearchTerm = 0 
And SearchFwMth = 0 Then

Dim queryMM = (From a In DBPricingContext.tbl_Matrix_Margins
               Where a.CompanyID = CInt(sCompanyID)
               Order By a.Profile
               Select a)
Return New StoreResult(queryMM)

ElseIf SearchMxMID > 0 
And SearchProfile = 0 
And SearchCZ =    "All" 
And SearchTerm = 0 
And SearchFwMth = 0 Then
Dim queryMM = (From a In DBPricingContext.tbl_Matrix_Margins
               Where a.CompanyID = CInt(sCompanyID) And a.MarGroupID = SearchMxMID
               Order By a.Profile
               Select a)
Return New StoreResult(queryMM)
等 等 等

这5个过滤器的每个组合的总次数为120次(无论它们是空的还是有值的)。有没有一种更快的方法可以做到这一点,可能是在一个Linq查询中

If SearchMxMID > 0 Then a.MarGroupID = SearchMxMID Else DO NOT APPLY WHERE CLAUSE

Linq查询是可链接的。你可以根据你的情况简单地使用一个if,如果它是真的,那么在where添加另一个if。ie(在C#中,但对于任何.Net编码器来说都应该很容易理解-或者您可以使用Telerik的代码转换器并稍微修改代码):

另一种方法是简单地使用NULL或。。。方法即:

Private Sub Main()
    Dim country As String = ""  '"Brazil"
    Dim city As String = "" '"Sao Paulo"
  Dim orderDate As System.Nullable(Of DateTime) = Nothing   'new DateTime(1996,8,28);

    Dim data = Orders.Where(Function(c) _
     String.IsNullOrEmpty(country) OrElse c.ShipCountry.StartsWith(country)) _
     .Where(Function(c) String.IsNullOrEmpty(city) OrElse c.ShipCity.StartsWith(city)) _
     .Where(Function(c) orderDate Is Nothing OrElse c.OrderDate = orderDate) _
     .Select(Function(c) New Order() With { _
         .OrderId = c.OrderID, _
         .CustomerId = c.CustomerID, _
         .OrderDate = c.OrderDate, _
         .ShipCountry = c.ShipCountry, _
         .ShipCity = c.ShipCity _
    })

    Dim f As New Form() With { .Text = "Query Results" }
    Dim dgv As New DataGridView() With { .Dock = DockStyle.Fill }
    f.Controls.Add(dgv)

    dgv.DataSource = data.ToList()
    f.ShowDialog()
End Sub

Public Class Order
    Public Property OrderId() As Integer
        Get
            Return m_OrderId
        End Get
        Set
            m_OrderId = Value
        End Set
    End Property
    Private m_OrderId As Integer
    Public Property OrderDate() As System.Nullable(Of DateTime)
        Get
            Return m_OrderDate
        End Get
        Set
            m_OrderDate = Value
        End Set
    End Property
    Private m_OrderDate As System.Nullable(Of DateTime)
    Public Property CustomerId() As String
        Get
            Return m_CustomerId
        End Get
        Set
            m_CustomerId = Value
        End Set
    End Property
    Private m_CustomerId As String
    Public Property ShipCountry() As String
        Get
            Return m_ShipCountry
        End Get
        Set
            m_ShipCountry = Value
        End Set
    End Property
    Private m_ShipCountry As String
    Public Property ShipCity() As String
        Get
            Return m_ShipCity
        End Get
        Set
            m_ShipCity = Value
        End Set
    End Property
    Private m_ShipCity As String
End Class

注意:代码是Linq到SQL代码。EF不支持这一点,您需要使用前一种方法。

您可以链接
Where
子句,并动态构建查询,如下所示:

Dim query = DBPricingContext.tbl_Matrix_Margins.AsQueryable()

If compID > 0 Then
    query = query.Where(Function(a) a.CompanyID = compID)
End If
If SearchMxMID > 0 Then
    query = query.Where(Function(a) a.MarGroupID = SearchMxMID)
End If
...

query = query.OrderBy(Function(a) a.Profile)
Sub Main()
        Dim someList As New List(Of SomeClass)

        Dim now As DateTime = DateTime.Now

        someList.Add(New SomeClass() With {.Id = 1, .Title = "001", .EntryDate = now})
        someList.Add(New SomeClass() With {.Id = 2, .Title = "002", .EntryDate = now.AddSeconds(10)})
        someList.Add(New SomeClass() With {.Id = 3, .Title = "003", .EntryDate = now.AddSeconds(20)})

        Dim idParam As Integer = 1
        Dim titleParam As String = "" '"001"
        Dim dateParam As DateTime = now



        ' first approach, one selector
        Dim selector As Func(Of SomeClass, Boolean) = Function(item)
                                                          With item
                                                              Return ((idParam <= 0) OrElse (.Id = idParam)) AndAlso
                                                                  ((String.IsNullOrEmpty(titleParam)) OrElse (.Title = titleParam)) AndAlso
                                                                  ((dateParam.CompareTo(DateTime.MinValue) = 0) OrElse (.EntryDate = dateParam))
                                                          End With
                                                      End Function



        Dim list = From o In someList Where selector(o) Select o

        For Each o In list
            Console.WriteLine(o)
        Next



        ' second approach, one selector per parameter
        Dim selectorId As Func(Of SomeClass, Boolean) = Function(item)
                                                            Return ((idParam <= 0) OrElse (item.Id = idParam))
                                                        End Function


        Dim selectorTitle As Func(Of SomeClass, Boolean) = Function(item)
                                                               Return ((String.IsNullOrEmpty(titleParam)) OrElse (item.Title = titleParam))
                                                           End Function


        Dim selectorEntryDate As Func(Of SomeClass, Boolean) = Function(item)
                                                                   Return ((dateParam.CompareTo(DateTime.MinValue) = 0) OrElse (item.EntryDate = dateParam))
                                                               End Function

        Dim list2 = From o In someList
                    Where
                    selectorId(o) AndAlso
                    selectorTitle(o) AndAlso
                    selectorEntryDate(o)
                    Select o

        For Each o In list2
            Console.WriteLine(o)
        Next

        Console.ReadLine()
    End Sub

    Public Class SomeClass
        Public Property Id As Integer
        Public Property Title As String
        Public Property EntryDate As DateTime

        Public Overrides Function ToString() As String
            Return String.Format("Id:{0}  Title:{1}  EntryDate:{2}", Id, Title, EntryDate)
        End Function
    End Class
这可以很好地扩展到许多列,因为每列只有一个If语句

注意,我使用的是扩展方法语法和lambda表达式,而不是专门的LINQ查询语法。如果只是选择参数
A
本身,则无需调用
Select


如果您使用LINQ to对象而不是LINQ to some_数据库,则将
AsQueryable()
替换为
AsEnumerable()

,您还可以使用LINQ语法串联组合查询

Dim TempQuery = (From a In DbPricingContext.tbl_Matrix_Margins
                 Where a.CompanyID = CInt(sCompanyID)
                 Select a)

If SearchMxMID > 0 Then
    TempQuery = (From a In TempQuery
                 Where a.MarGroupID = SearchMxMID
                 Select a)
End If

'... Add your other conditions in here...

Return New StoreResult(From a In TempQuery Order By a.Profile Select a)

使用逻辑,如
SearchValue=DefaultValue或lse SearchValue=PropertyValue

Dim result = DBPricingContext.tbl_Matrix_Margins.
                 Where(Function(a) a.CompanyID = CInt(sCompanyID)).
                 Where(Function(a) SearchMxMID = 0 OrElse a.MarGroupID = SearchMxMID)
并以相同方式添加其他搜索条件。
如果
SearchMxMID=0
它将返回所有行,如果
SearchMxMID 0

对于精度结果,我将使用
Nullable
类型

Where(Function(a) SearchMxMID.HasValue = False OrElse a.MarGroupID = SearchMxMID.Value)

您可以实现一个规范模式。大概是这样的:

Dim query = DBPricingContext.tbl_Matrix_Margins.AsQueryable()

If compID > 0 Then
    query = query.Where(Function(a) a.CompanyID = compID)
End If
If SearchMxMID > 0 Then
    query = query.Where(Function(a) a.MarGroupID = SearchMxMID)
End If
...

query = query.OrderBy(Function(a) a.Profile)
Sub Main()
        Dim someList As New List(Of SomeClass)

        Dim now As DateTime = DateTime.Now

        someList.Add(New SomeClass() With {.Id = 1, .Title = "001", .EntryDate = now})
        someList.Add(New SomeClass() With {.Id = 2, .Title = "002", .EntryDate = now.AddSeconds(10)})
        someList.Add(New SomeClass() With {.Id = 3, .Title = "003", .EntryDate = now.AddSeconds(20)})

        Dim idParam As Integer = 1
        Dim titleParam As String = "" '"001"
        Dim dateParam As DateTime = now



        ' first approach, one selector
        Dim selector As Func(Of SomeClass, Boolean) = Function(item)
                                                          With item
                                                              Return ((idParam <= 0) OrElse (.Id = idParam)) AndAlso
                                                                  ((String.IsNullOrEmpty(titleParam)) OrElse (.Title = titleParam)) AndAlso
                                                                  ((dateParam.CompareTo(DateTime.MinValue) = 0) OrElse (.EntryDate = dateParam))
                                                          End With
                                                      End Function



        Dim list = From o In someList Where selector(o) Select o

        For Each o In list
            Console.WriteLine(o)
        Next



        ' second approach, one selector per parameter
        Dim selectorId As Func(Of SomeClass, Boolean) = Function(item)
                                                            Return ((idParam <= 0) OrElse (item.Id = idParam))
                                                        End Function


        Dim selectorTitle As Func(Of SomeClass, Boolean) = Function(item)
                                                               Return ((String.IsNullOrEmpty(titleParam)) OrElse (item.Title = titleParam))
                                                           End Function


        Dim selectorEntryDate As Func(Of SomeClass, Boolean) = Function(item)
                                                                   Return ((dateParam.CompareTo(DateTime.MinValue) = 0) OrElse (item.EntryDate = dateParam))
                                                               End Function

        Dim list2 = From o In someList
                    Where
                    selectorId(o) AndAlso
                    selectorTitle(o) AndAlso
                    selectorEntryDate(o)
                    Select o

        For Each o In list2
            Console.WriteLine(o)
        Next

        Console.ReadLine()
    End Sub

    Public Class SomeClass
        Public Property Id As Integer
        Public Property Title As String
        Public Property EntryDate As DateTime

        Public Overrides Function ToString() As String
            Return String.Format("Id:{0}  Title:{1}  EntryDate:{2}", Id, Title, EntryDate)
        End Function
    End Class
Sub-Main()
将someList设置为新列表(SomeClass的)
立即变暗为DateTime=DateTime.now
添加(带有{.Id=1、.Title=“001”、.EntryDate=now}的新SomeClass())
添加(带有{.Id=2、.Title=“002”、.EntryDate=now.AddSeconds(10)}的新SomeClass())
添加(带有{.Id=3、.Title=“003”、.EntryDate=now.AddSeconds(20)}的新SomeClass())
Dim idParam为整数=1
将标题参数设置为字符串=“001”
Dim dateParam As DateTime=now
“第一种方法,一个选择器
Dim选择器为Func(属于某个类,布尔)=函数(项)
带项目
返回((idParam场景:我的结果集中有5个可过滤列。我必须考虑这5个过滤器在任何给定时间的所有变化。这意味着我必须手动键入一个包含120个不同变化的If/ElseIf语句!不,你不需要。只使用相关的-是的,你的where块有5个If语句,但是你只需要插入值。我一直在SQL中这样做,所以在Linq中也应该可以。我在SQL中使用,Linq中也有类似的功能。