2011-09-09 38 views
2

如何根据客户端提供的值动态排序实体框架查询?LINQ to Entities根据客户端输入排序表达式

我有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

这是一个典型的情况。有人可以指导我一个正确的解决方案? – anotherNeo

回答

1

而不是试图让帮助程序类能够返回可用于OrderBy(降序)方法调用中的通用表达式(当数据类型不完全相同时,您发现它很困难),在辅助方法中执行对OrderBy(降序)的调用会容易得多。例如:

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); 

你也可以改变转换方法的签名,包括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)