具有动态构建的linq谓词的扩展方法

时间:2010-10-21 00:03:59

标签: c# linq extension-methods

我有这种扩展方法。

        public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        var property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "SelectMany",
                                            new Type[] { source.ElementType, property.Type },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }

我收到此错误

 No method 'SelectMany' on type 'System.Linq.Queryable' is compatible with the         supplied arguments.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: No method 'SelectMany' on type 'System.Linq.Queryable' is compatible with the supplied arguments.

Source Error:

Line 67:             LambdaExpression lambda = Expression.Lambda(property, parameter);
Line 68: 
Line 69:             Expression methodCallExpression = Expression.Call(typeof(Queryable), "SelectMany",
Line 70:                                                 new Type[] { source.ElementType, property.Type },
Line 71:                                                 source.Expression, Expression.Quote(lambda));

当我从像这样的实体框架中调用这个方法时

this.grdReservations.DataSource = dataContext.CustomerSet.SearchBy(crit);

这是SearchCriteria

        SearchCriteria crit = new SearchCriteria();
        crit.Property = "UserName";
        crit.PropertyValue = "new_user";
        crit.Search = SearchType.Equal;

如果有人能看一眼并向我推进正确的方向,我会非常高兴。

感谢您的时间。

编辑:我在家,所以我无法测试,但我尝试的任何方法(“选择”,“在哪里”,“SelectMany”)都返回了这个错误,所以我假设我正在做其他事情错误。

3 个答案:

答案 0 :(得分:1)

您想要拨打SelectMany还是只选择?

SelectMany期望lambda返回一个IEnumerable [TResult]而不是TResult。

答案 1 :(得分:1)

 this works

public static IQueryable<T> SearchBy<T>(this IQueryable<T> source, SearchCriteria criteria)
    {
        //throw an error if the source is null
        if (source == null)
        {
            throw new ArgumentNullException("source");
        }

        ParameterExpression parameter = Expression.Parameter(source.ElementType, string.Empty);
        BinaryExpression property = Expression.Equal(Expression.PropertyOrField(parameter, criteria.Property), Expression.Constant(criteria.PropertyValue));
        LambdaExpression lambda = Expression.Lambda(property, parameter);

        Expression methodCallExpression = Expression.Call(typeof(Queryable), "Where",
                                            new Type[] { source.ElementType },
                                            source.Expression, Expression.Quote(lambda));

        return source.Provider.CreateQuery<T>(methodCallExpression);
    }

我需要将Expression.Call类型数组更改为此

new Type[] { source.ElementType }

This Example非常有帮助。

感谢您的时间

答案 2 :(得分:0)

lambda似乎采用类型为T的参数值并返回一个bool。它看起来应该返回一个IEnumerable。

或者,如果将“SelectMany”更改为“Select”,则lambda将需要返回T类型的值。