LINQ to Entities根据客户端输入对表达式进行排序

时间:2011-09-09 15:54:58

标签: c# entity-framework sorting linq-to-entities expression

如何根据客户端提供的值动态对实体框架查询进行排序?

我有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可以正常工作。

我怎样才能让它发挥作用?

1 个答案:

答案 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)