我在前端有一个带有多列和分页的表。用户应该能够对他想要的列进行排序,如果他移动到下一页,那么该页也应该按给定的列排序。
我使用单一排序键和分页的方法:
public List<Person> GetPersons(int page, int numPerPage)
{
return _context.Person
.OrderByDescending(p => p.FirstName)
.Skip(page*numPerPage)
.Take(numPerPage)
}
这仅限于按FirstName
排序,但如何使用例如LastName
、Address
等进行排序。。。?
OrderByDescending
采用一个具有两个类型参数的函数:Expression<Func<TSource, TKey>>
,其中TKey
表示表达式返回的键的类型。
因此,您可以将一个表达式传递给您的方法,并在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);
}
TKey
类型参数由表达式推断。因此,它可以如下使用:
var byName = GetPersons(page, pageSize, p => p.FirstName);
var byDate = GetPersons(page, pageSize, p => p.DateOfBirth);
var byHeight = GetPersons(page, pageSize, p => p.Height);
如果要应用筛选/搜索,则向该方法添加一个新表达式并使用Where
:
public List<Person> GetPersons<TKey>(int page, int numPerPage,
Expression<Func<Person, bool>> filter,
Expression<Func<Person, TKey>> orderByDesc)
{
return _context.Person
.Where(filter)
.OrderByDescending(orderByDesc)
.Skip(page*numPerPage)
.Take(numPerPage);
}
// filter by FirstName, order by LastName
var filtered = GetPersons(page, pageSize,
p => p.FirstName == "Bob", // filter
p => p.LastName); // orderBy
试试这个扩展方法:
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);
}
您可以将属性名称作为字符串传递,如FirstName
、LastName
或Address
等。因此,您可以动态订购Persons
。
public List<Person> GetPersons(int page, int numPerPage, string orderFieldName)
{
return _context.Person
.OrderByField(orderFieldName, false)
.Skip(page*numPerPage)
.Take(numPerPage)
}
请参阅:如何使用表达式树构建动态查询
编辑:
另一种可能的解决方案是使用System.Linq.Dynamic
,请参阅:https://stackoverflow.com/a/8660293/5519709