No generic method 'ThenBy' on type 'System.Linq.Queryable'

前端 未结 1 733
鱼传尺愫
鱼传尺愫 2021-01-17 04:44

I\'m trying to create a generic OrderBy(fields collection) method to use in a new EF .Net Core 2.1 and managed to write the below code:

 pub         


        
相关标签:
1条回答
  • 2021-01-17 05:25

    I feel you are overcomplicating everything:

    // Or IEnumerable<SortColumn> columns
    public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetOrderByFunction<TEntity>(params SortColumn[] columns)
    {
        Type typeQueryable = typeof(IQueryable<TEntity>);
        ParameterExpression argQueryable = Expression.Parameter(typeQueryable, "p");
        Type entityType = typeof(TEntity);
    
        ParameterExpression arg = Expression.Parameter(entityType, "x");
    
        Expression resultExp = argQueryable;
    
        bool first = true;
    
        foreach (SortColumn sc in columns)
        {
            PropertyInfo pi = entityType.GetProperty(sc.FieldName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
            Expression propertyExpr = Expression.Property(arg, pi);
            Type propertyType = pi.PropertyType;
            LambdaExpression lambdaExp = Expression.Lambda(propertyExpr, arg);
    
            string methodName;
    
            if (first)
            {
                first = false;
    
                methodName = sc.Descending ? "OrderBy" : "OrderByDescending";
            }
            else
            {
                methodName = sc.Descending ? "ThenBy" : "ThenByDescending";
            }
    
            resultExp = Expression.Call(typeof(Queryable), methodName, new Type[] { entityType, propertyType }, resultExp, Expression.Quote(lambdaExp));
        }
    
        // Case empty columns: simply append a .OrderBy(x => true)
        if (first)
        {
            LambdaExpression lambdaExp = Expression.Lambda(Expression.Constant(true), arg);
            resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { entityType, typeof(bool) }, resultExp, Expression.Quote(lambdaExp));
        }
    
        LambdaExpression orderedLambda = Expression.Lambda(resultExp, argQueryable);
        return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)orderedLambda.Compile();
    }
    

    I'll add that calling FieldName what is really a PropertyName is a little... misleading :-)

    Note that I've added the case for when columns is empty: this because you return a IOrderedQueryable, so an ordering must always be present.

    0 讨论(0)
提交回复
热议问题