I have a table in the frontend with multiple columns and pagination. The user should be able to sort which columns he wants, and if he moves to the next page, that page should also be sorted by the given column.
My approach with a single sort key and pagination:
public List<Person> GetPersons(int page, int numPerPage)
{
return _context.Person
.OrderByDescending(p => p.FirstName)
.Skip(page*numPerPage)
.Take(numPerPage)
}
This is limited to only sorting by FirstName
, but how can I do this with e.g. LastName
, Address
etc...?
CodePudding user response:
Try this extension method:
public static IQueryable<T> OrderByField<T>(this IQueryable<T> q, string SortField, bool Ascending)
{
var param = Expression.Parameter(typeof(T), "p");
var prop = Expression.Property(param, SortField);
var exp = Expression.Lambda(prop, param);
string method = Ascending ? "OrderBy" : "OrderByDescending";
Type[] types = new Type[] { q.ElementType, exp.Body.Type };
var mce = Expression.Call(typeof(Queryable), method, types, q.Expression, exp);
return q.Provider.CreateQuery<T>(mce);
}
And you can pass property name as a string like FirstName
, LastName
or Address
etc.. Thus you can order Persons
dynamically.
public List<Person> GetPersons(int page, int numPerPage, string orderFieldName)
{
return _context.Person
.OrderByField(orderFieldName, false)
.Skip(page*numPerPage)
.Take(numPerPage)
}
See: How to use expression trees to build dynamic queries
EDIT:
Another possible solution is using System.Linq.Dynamic
see: https://stackoverflow.com/a/8660293/5519709
CodePudding user response:
OrderByDescending
takes a function with 2 type parameters: Expression<Func<TSource, TKey>>
where TKey
represents the type of the key returned by the expression.
Therefore, you could pass an expression to your method and use in the OrderBy:
public List<Person> GetPersons<TKey>(int page, int numPerPage,
Expression<Func<Person, TKey>> orderByDesc)
{
return _context.Person
.OrderByDescending(orderByDesc)
.Skip(page*numPerPage)
.Take(numPerPage);
}
The TKey
type parameter is inferred by the expression. So, it can be used as below:
var byName = GetPersons(page, pageSize, p => p.FirstName);
var byDate = GetPersons(page, pageSize, p => p.DateOfBirth);
var byHeight = GetPersons(page, pageSize, p => p.Height);