使用分页动态Linq到实体的顺序

时间:2016-12-09 21:00:08

标签: c# linq model-view-controller linq-to-entities

我有一个超过800k记录的SQL表,需要在网页上以25个结果显示。我需要能够从表中搜索和排序这些结果,但由于表太大,我无法在过滤/排序之前将所有结果都拉到IEnumerable(我以前这样做并且它起作用了,但它现在令人难以置信慢慢做初始拉动。)

我已经找到了搜索,但这种情况真的搞砸了我。我花了几个小时研究它,但在.Skip()之前找不到任何有效的解决方案。Take()。

我需要能够做到这样的事情:

string sortField = "Name"; //just for example
string sortDirection = "descending"; //also for example
List<People> = (from s in db.People
                orderby sortField sortDirection
                select s).Skip((page - 1) * pageSize).Take(pageSize).ToList();

People中的可排序列可以是DateTime,int或字符串,因此我尝试执行类似

的操作
orderby (
    currentSort == "Name" ? s.Name : 
    currentSort = "SignUpDate" ? s.SignupDate : s.Id
)

是徒劳的,因为程序抱怨混合类型。

有什么办法可以让这项工作成功吗?提前感谢任何帮助或潜在客户!

1 个答案:

答案 0 :(得分:2)

您可以使用以下自定义扩展方法,使用OrderBy(Descending)类动态构建System.Linq.Expressions.Expression调用(类似于How to use a string to create a EF order by expression?):

public static partial class QueryableExtensions
{
    public static IOrderedQueryable<T> OrderByMember<T>(this IQueryable<T> source, string memberPath, bool descending)
    {
        var parameter = Expression.Parameter(typeof(T), "item");
        var member = memberPath.Split('.')
            .Aggregate((Expression)parameter, Expression.PropertyOrField);
        var keySelector = Expression.Lambda(member, parameter);
        var methodCall = Expression.Call(
            typeof(Queryable), descending ? "OrderByDescending" : "OrderBy", 
            new[] { parameter.Type, member.Type },
            source.Expression, Expression.Quote(keySelector));
        return (IOrderedQueryable<T>)source.Provider.CreateQuery(methodCall);
    }
}
像这样:

var people = db.People
    .OrderByMember(sortField, sortDirection == "descending")
    .Skip((page - 1) * pageSize).Take(pageSize)
    .ToList();