Building dynamic where logic in LINQ

If you need to dynamically build and/or logic in your LINQ query, you can use predicates and the PredicateBuilder pattern described here.  My current client uses VB.NET so there really couldn’t use the source that is provided in that article, so their only choice was going to be to reference the LINQKit assembly provided by the author (great C# book, by the way).  It seemed silly to me to have to include that assembly for such small functionality since they are not using any of its other features, it would be another assembly that would need to be added to their distributable.  So I translated the code to VB and added it to their project:

Imports System
Imports System.Linq
Imports System.Linq.Expressions
Imports System.Collections.Generic
Imports System.Runtime.CompilerServices
Public Module PredicateBuilder
    Public Function [True](Of T)() As Expression(Of Func(Of T, Boolean))
        Return Function(f) True
    End Function

    Public Function [False](Of T)() As Expression(Of Func(Of T, Boolean))
        Return Function(f) False
    End Function

     _
    Public Function [Or](Of T)(ByVal expr1 As Expression(Of Func(Of T, Boolean)), ByVal expr2 As Expression(Of Func(Of T, Boolean))) As Expression(Of Func(Of T, Boolean))
        Dim invokedExpr = Expression.Invoke(expr2, Enumerable.Cast(Of Expression)(expr1.Parameters))
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters)
    End Function

     _
    Public Function [And](Of T)(ByVal expr1 As Expression(Of Func(Of T, Boolean)), ByVal expr2 As Expression(Of Func(Of T, Boolean))) As Expression(Of Func(Of T, Boolean))
        Dim invokedExpr = Expression.Invoke(expr2, Enumerable.Cast(Of Expression)(expr1.Parameters))
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters)
    End Function
End Module

 

It had been a long time since I did any VB coding so it was a pain to figure out at first, but got it to work, so the code above translates directly to the C# sample used in LINQKit.  I guess for the non-VB-speaking C# developers out there, as far as I can tell, a Module is a just a static class.

Once you have that in place you can do things like:

Dim predicate = PredicateBuilder.False(Of myType)()
predicate = predicate.Or(Function(p) p.StartDate = "1/1/2008")
If (includeEndDate) Then
    predicate = predicate.Or(Function(p) p.EndDate = "12/31/2008")
End If

Dim myList = From b In mycontext.myTable.Where(predicate).ToList()

Scroll to Top