Skip to content

Table sorting #5613

@rwb196884

Description

@rwb196884

Is there an existing issue for this?

  • I have searched the existing issues

Is your feature request related to a problem? Please describe the problem.

The class BootstrapBlazor.Components.QueryPageOptionsExtensions contains methods for converting what's in QueryPageOptions to LINQ, but not the sort options.

I think you need something like this:

     public static class MoreQueryPageOptionsExtensions
    {
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T">
        /// <para>Must be an EF entity in order to transpile the whole query chain to SQL.</para>
        /// <para>If not then use an anonymous type with the mapped entity as a property and use the complexProperty parameter on the other overload.</para>
        /// 
        /// </typeparam>
        /// <param name="source"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static IQueryable<T> Apply<T>(this IQueryable<T> source, QueryPageOptions? options)
        {
            return Apply<T, T>(source, options, z => z);
        }

        public static IQueryable<T> Apply<T, U>(this IQueryable<T> source, QueryPageOptions? options, Expression<Func<T, U>> complexProperty)
        {
            if(options == null) { return source; }
            return source
                .Where(z => BootstrapBlazor.Components.QueryPageOptionsExtensions.ToFilterFunc<T>(options)(z))
                .Order(options, complexProperty)
                .Skip(options.PageIndex * options.PageItems).Take(options.PageItems);
        }

        private static IQueryable<T> Order<T, U>(this IQueryable<T> source, QueryPageOptions options, Expression<Func<T, U>> complexProperty)
        {
            if (string.IsNullOrEmpty(options.SortName)) { return source; }

            MemberExpression cPme = (MemberExpression)complexProperty.Body;

            // https://stackoverflow.com/questions/16208214/construct-lambdaexpression-for-nested-property-from-string
            ParameterExpression z = Expression.Parameter(typeof(T), "z");
            MemberExpression zm = Expression.PropertyOrField(z, cPme.Member.Name);
            zm = Expression.PropertyOrField(zm, options.SortName);
             
            Type tT = typeof(T);
            PropertyInfo p = typeof(U).GetProperty(options.SortName);

            Type funcType = typeof(Func<,>).MakeGenericType(tT, p.PropertyType);
            LambdaExpression composition = Expression.Lambda(funcType, zm, z);

            Type tQ = typeof(System.Linq.Queryable);
            MethodInfo tQm = tQ.GetMethods(BindingFlags.Public | BindingFlags.Static).Single(z => z.Name == (options.SortOrder == SortOrder.Desc ? "OrderByDescending" : "OrderBy") && z.GetParameters().Count() == 2);
            MethodInfo tQmg = tQm.MakeGenericMethod(tT, p.PropertyType);
            var r = tQmg.Invoke(null, new object[] { source, composition });
            return (IQueryable<T>)r;
        }
    }

Need to make the Where work with the compledProperty...

Example of use

        IQueryable<ItemCategoryWithCount> data = db.ItemCategories.Join(db.ItemSpecifications, z => z.CategoryId, z => z.ItemCategoryId, (ItemCategory c, ItemSpecification s) => new { ItemCategory = c, Item = s })
    .GroupBy(z => z.ItemCategory)
    .Select(z => new { ItemCategory = z.Key, Count = z.Count() }) // Projection to anonymous type allows transpilation of Apply.
    .Apply(options, z => z.ItemCategory)
    .Select(z => new ItemCategoryWithCount(z.ItemCategory, z.Count))
    ;

Describe the solution you'd like

No response

Additional context

No response

Metadata

Metadata

Assignees

Labels

questionQuestion that needs to be answered

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions