Search code examples
vb.netnhibernatepredicatebuilder

Fluent, NHibernate, and PredicateBuilder


Fluent v1.4, NHibernate v4.0.2.4000, SQL Server

I've seen some posts where Predicate Builder with nested Lambda expressions are not evaluated in NHibernate v3. Could it be that v4 also has this problem?

Public Function TestingWorldQuery() As List(Of EmployeeView)
    Dim EmpView = From q In m_Session.Query(Of EmployeeView)() 
    Dim expr = PredicateBuilder.False(Of EmployeeView)()
    For Each _opco In {"AGRI", "CORP", "FOODS"}
        Dim opco As String = _opco
        expr = expr.Or(Function(x) x.OpCoOrgId = opco)
    Next
    EmpView = EmpView.Where(expr)
    Return EmpView.ToList
End Function

Unable to cast object of type 'NHibernate.Hql.Ast.HqlBitwiseOr' to type 'NHibernate.Hql.Ast.HqlBooleanExpression'


CORRECTION -- After Felipe's suggestion I modified my VB.NET PredicateBuilder Code to use OrElse. My code is now working.

Imports System.Linq.Expressions

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

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [OrElse](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, expr1.Parameters.Cast(Of Expression)())
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.[OrElse](expr1.Body, invokedExpr), expr1.Parameters)
    End Function

    <System.Runtime.CompilerServices.Extension()> _
    Public Function [AndAlso](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, expr1.Parameters.Cast(Of Expression)())
        Return Expression.Lambda(Of Func(Of T, Boolean))(Expression.[AndAlso](expr1.Body, invokedExpr), expr1.Parameters)
    End Function
End Module

Solution

  • In VB.Net we have Or and OrElse, you should prefer using the OrElse instead Or because Or is bitwised. Take a look at PredicateBuilder you have and see if you are using Expression.Or or Expression.OrElse. Change it to OrElse if necessary. It is like in C# | for Or and || for OrElse.

    You could try it using the Contains method, which will generate an IN sql statement instead of Or. Try this:

    Public Function TestingWorldQuery() As List(Of EmployeeView)
    
       Return m_Session.Query(Of EmployeeView)().Where(Function(x) {"AGRI", "CORP", "FOODS"}.Contains(x.OpCoOrgId)).ToList()
    
    End Function
    

    Obs: I didn't tested it.