如何使用近似值对LINQ to SQL查询的结果进行排序?

时间:2018-06-09 04:01:48

标签: vb.net linq

我为LINQ to OBJECTS编写了以下扩展方法,它完全符合我的要求,但我无法使用LINQ to SQL。

 <Extension()> Public Function ThenByLike(Of T As Class)(ByVal items As IOrderedEnumerable(Of T), PropertySelector As Func(Of T, String), Ascending As Boolean, ParamArray Searches As String()) As IOrderedEnumerable(Of T)
        Searches = If(Searches, {})
        If Searches.Count > 0 Then
            For Each t In Searches
                For Each exp In {
                    Function(x) PropertySelector(x) = t,
                    Function(x) PropertySelector(x).StartsWith(t),
                    Function(x) PropertySelector(x).Contains(t),
                    Function(x) PropertySelector(x).EndsWith(t)
                  }

                    If Ascending Then
                        items = items.ThenByDescending(exp)
                    Else
                        items = items.ThenBy(exp)
                    End If
                Next
            Next
        End If


        Return items
    End Function

我得到以下异常:

  

方法'System.Object DynamicInvoke(System.Object [])'不受支持   转换为SQL。

要使该方法与LINQ to SQL兼容,我需要做什么?

1 个答案:

答案 0 :(得分:0)

我找到了解决方案。我需要将该函数转换为以下代码,以获取在SQL Server上运行的有效SQL查询。

 <Extension()> Public Function ThenByLike(Of T)(ByVal items As IOrderedQueryable(Of T), Searches As String(), SortProperty As Expression(Of Func(Of T, String)), Optional Ascending As Boolean = True) As IOrderedQueryable(Of T)
        Dim type = GetType(T)
        Searches = If(Searches, {})
        For Each t In Searches
            Dim mem As MemberExpression = SortProperty.Body
            Dim [property] = mem.Member
            Dim parameter = SortProperty.Parameters.First
            Dim propertyAccess = Expression.MakeMemberAccess(parameter, [property])
            Dim orderByExp = Expression.Lambda(propertyAccess, parameter)

            Dim tests As MethodCallExpression() = {
                    Expression.Call(propertyAccess, startsWithMethod, Expression.Constant(t)),
                    Expression.Call(propertyAccess, containsMethod, Expression.Constant(t)),
                    Expression.Call(propertyAccess, endsWithMethod, Expression.Constant(t))
                    }

            For Each exp In tests
                Dim nv = Expression.Lambda(Of Func(Of T, Boolean))(exp, parameter)
                If Ascending Then
                    items = items.ThenByDescending(nv)
                Else
                    items = items.ThenBy(nv)
                End If
            Next

        Next
        Return items
    End Function

    Private containsMethod As MethodInfo = GetType(String).GetMethod("Contains")

    Private endsWithMethod As MethodInfo = GetType(String).GetMethod("EndsWith", {GetType(String)})

    Private startsWithMethod As MethodInfo = GetType(String).GetMethod("StartsWith", {GetType(String)})