如何根据客户端提供的值动态对实体框架查询进行排序?
我有2个用户输入:一个是过滤项目的值,另一个是按结果排序的方式 - 按日期,状态,优先级或类型。
数据显示在网格中。
我有一个这样的查询:
Expression<Func<Issue, object>> sortExpression = IssuesConversionsFilter.Convert(sortBy);
Requests = query.Where(i => i.Project.ProjectID == projectId && i.Project.Enabled)
.OrderByDescending(sortExpression)
.Skip(( currentPage - 1 )*take)
.Take(take)
IssuesConversionFilter是一个静态类,其缓存由枚举键控并且值为Expression<Func<Issue, object>>
:
internal static class IssuesConversionsFilter
{
readonly static IDictionary<IssuesSortBy, Expression<Func<Issue, object>>> Cache = new Dictionary<IssuesSortBy, Expression<Func<Issue, object>>>();
static IssuesConversionsFilter() {
Cache.Add(IssuesSortBy.Date, i => i.CreatedDate);
Cache.Add(IssuesSortBy.Priority, i => i.Priority);
Cache.Add(IssuesSortBy.Type, i => i.Type);
Cache.Add(IssuesSortBy.State, i => i.State);
}
public static Expression<Func<Issue, object>> Convert(IssuesSortBy sortBy) {
if(Cache.ContainsKey(sortBy) == false)
throw new InvalidOperationException();
return Cache[sortBy];
}
}
返回类型必须是一个只返回object
和LINQ to Entities的表达式的问题似乎只支持基本类型。使用LING-to-Objects可以正常工作。
我怎样才能让它发挥作用?
答案 0 :(得分:1)
而不是试图让helper类能够返回一个可以在OrderBy(Descending)方法调用中使用的泛型表达式(当数据类型不完全相同时,你发现它很难) ,在helper方法中执行对OrderBy(Descending)的调用会容易得多。例如:
internal static class IssuesConversionsFilter
{
public static IOrderedQueryable<Issue> Convert(IQueryable<Issue> query, IssuesSortBy sortBy)
{
switch (sortBy)
{
case IssuesSortBy.Date:
return query.OrderByDescending(i => i.CreatedDate);
case IssuesSortBy.Priority:
return query.OrderByDescending(i => i.Priority);
case IssuesSortBy.Type:
return query.OrderByDescending(i => i.Type);
case IssuesSortBy.State:
return query.OrderByDescending(i => i.State);
default:
throw new ArgumentOutOfRangeException("sortBy");
}
}
}
然后您可以像这样使用该方法:
var orderedQuery = IssuesConversionsFilter.Convert(unOrderedQuery, IssuesSortBy.Date);
您还可以更改Convert方法的签名以包含this
:
public static IOrderedQueryable<Issue> Convert(this IQueryable<Issue> query, IssuesSortBy sortBy)
然后你就可以将它用作扩展方法。这样,您将保持示例中的流畅调用样式:
var Requests = query.Where(i => i.Project.ProjectID == projectId && i.Project.Enabled)
.Convert(sortBy)
.Skip(( currentPage - 1 )*take)
.Take(take)