实体框架-LINQ:动态谓词生成器问题



我正在尝试创建一个助手类来轻松构建动态LINQ查询。代码是这篇优秀的CodeProject文章的经过大量修改的版本:http://www.codeproject.com/Articles/493917/Dynamic-Querying-with-LINQ-to-Entities-and-Express它在这里使用PredicateBuilder:http://www.albahari.com/nutshell/predicatebuilder.aspx

我仍在清理代码,所以变量名称目前是垃圾,看不到任何注释。

用法

    Dim conditions As New List(Of Condition)
    With conditions
        .Add(New Condition With {.Field = "EatsPeople", .Operator = "Equals", .Value = False})
        .Add(New Condition With {.Field = "Name", .Operator = "Equals", .Value = "Adric"})
        .Add(New Condition With {.Field = "Description", .Operator = "Contains", .Value = "ugly"})
    End With
    Dim predicate = BuildPredicate(conditions)
    Dim tester = data.Monsters.AsExpandable.Where(predicate).ToList

实体

Public Class Monster
    Public Property EatsPeople As Boolean
    Public Property Name As String
    Public Property Description As String
End Class

用于搜索的存储

Public Class Condition
    Public Property Field As String
    Public Property [Operator] As String
    Public Property Value As Object
End Class

方法

Public Function BuildPredicate(conditions As List(Of Condition)) As Expression(Of Func(Of Monster, Boolean))
    Dim predicate = PredicateBuilder.True(Of Monster)()
    For Each c In conditions
        Dim dbFieldName = c.Field
        Dim dbType = GetType(Monster)
        Dim dbFieldMemberInfo = dbType.GetMember(dbFieldName, BindingFlags.IgnoreCase Or BindingFlags.Public Or BindingFlags.Instance).Single()
        predicate = BuildExpression(c, dbType, dbFieldMemberInfo, predicate)
    Next
    Return predicate
End Function
Private Function CreateLambda(value As Object, method As MethodInfo, ByVal dbType As Type, ByVal dbFieldMemberInfo As MemberInfo) As Expression(Of Func(Of Monster, Boolean))
    Dim dbTypeParameter = Expression.Parameter(dbType, "x")
    Dim dbFieldMember = Expression.MakeMemberAccess(dbTypeParameter, dbFieldMemberInfo)
    Dim criterionConstant = New Expression() {Expression.Constant(value)}
    Dim containsCall = Expression.Call(dbFieldMember, method, criterionConstant)
    Return TryCast(Expression.Lambda(containsCall, dbTypeParameter), Expression(Of Func(Of Monster, Boolean)))
End Function

和有问题的方法

Private Function BuildExpression(condition As Condition, ByVal dbType As Type, ByVal dbFieldMemberInfo As MemberInfo, ByVal predicate As Expression(Of Func(Of Monster, Boolean))) As Expression(Of Func(Of Monster, Boolean))
    Dim type = condition.Value.GetType
    Dim method As MethodInfo = type.GetMethod(condition.Operator, BindingFlags.Instance Or BindingFlags.Public, Nothing, {type}, Nothing)
    If type = GetType(String) Then
        If condition.Value.ToString.Contains(",") = True Then
            Dim inner = PredicateBuilder.False(Of Product)()
            For Each v In condition.Value.ToString.Split(",")
                inner = inner.Or(CreateLambda(v, method, dbType, dbFieldMemberInfo))
            Next     
            *****Return predicate.And(inner)*****
        End If
    End If
    Return predicate.And(CreateLambda(condition.Value, method, dbType, dbFieldMemberInfo))
End Function

问题出在哪里

最后一种方法中被五个星号包围的线就是问题所在。

当将OR分组表达式添加到原始谓词生成器时,您将获得

参数"f"未绑定在指定的LINQ to Entities中查询表达式。

出于某种原因,我似乎无法创建嵌套表达式。如果你把上面的代码放在使用示例中执行查询的地方,它就可以工作了(在制作了一些mod之后)。

使用解决方案更新:

带星号的行需要更改为Return predicate.And(inner.Expand)

我不是Visual Basic人员,但在C#实现中,我认为您可能需要根据albahari.com/nutshell/pedicatebuilder.aspx.

将AsExpandable()添加到查询中

相关内容

  • 没有找到相关文章

最新更新