C# 为orderby语句添加通用分类器表达式

C# 为orderby语句添加通用分类器表达式,c#,.net,linq,entity-framework,C#,.net,Linq,Entity Framework,(我简化了所有代码,使其只包含特定问题) 我创建了两种不同的服务方法,它们接受排序表达式,我想在ORDERBY语句中使用排序表达式 两个版本如下: public List<Order> GetOrders(Expression<Func<Order, object>> sortExpression) { // get the query for the orders table IQueryable<Order> query = G

(我简化了所有代码,使其只包含特定问题)

我创建了两种不同的服务方法,它们接受排序表达式,我想在ORDERBY语句中使用排序表达式

两个版本如下:

public List<Order> GetOrders(Expression<Func<Order, object>> sortExpression)
{
    // get the query for the orders table
    IQueryable<Order> query = GetQuery();

    // order by based on the passed in expression
    query = query.OrderBy(sortExpression);

    // now execute the query and return the collection
    return query.ToList();
}

public List<Order> GetOrders2(Func<IQueryable<Order>, IOrderedQueryable<Order>> orderby)
{
    IQueryable<Order> dbQuery = GetQuery();

    if (orderby != null)
    {
        dbQuery = orderby(dbQuery);
    }

    return dbQuery.ToList();
}
如果我只传入某些类型,那么第一个方法可以很好地工作。如果我传入一个
DateTime
或一个
Nullable
类型,那么它会抛出一个异常,即它无法将这些类型强制转换为
对象

如果传入一个排序表达式,则第二个方法可以正常工作。但如果我尝试传入一个集合(或参数),我能让它工作的唯一方法基本上是最后一个排序顺序覆盖上一个排序顺序


我如何更改其中一个,使其接受多个排序表达式,它处理
OrderBy
然后by
,并且它适用于所有类型?

因此,首先,如果您只想为
GetOrders
提供lambda,那么您需要接受
表达式,而不是现有的表达式

要接受任意数量的选择器,最方便的方法(对于调用者)是对此类参数使用
params

此时,只需在第一个选择器上排序,然后在所有后续选择器上调用
然后再调用

public List<Order> GetOrders(params Expression<Func<Order, object>>[] selectors)
{
    var dbQuery = GetQuery();

    if (selectors.Any())
    {
        var orderedQuery = dbQuery.OrderBy(selectors.First());

        foreach (var selector in selectors.Skip(1))
            orderedQuery = orderedQuery.ThenBy(selector);
        dbQuery = orderedQuery;
    }

    return dbQuery.ToList();
}
public List GetOrders(参数表达式[]选择器)
{
var dbQuery=GetQuery();
if(选择器.Any())
{
var orderedQuery=dbQuery.OrderBy(selectors.First());
foreach(选择器中的变量选择器。跳过(1))
orderedQuery=orderedQuery.ThenBy(选择器);
dbQuery=orderedQuery;
}
返回dbQuery.ToList();
}

考虑到您的示例似乎提供了一个
Func
但是您的方法使用的是
Func
类型的参数,我会很惊讶,这里是否缺少
GetOrders
重载?啊,我需要回到该方法。我有几个不同的版本在尝试不同的东西,并且在我赶出去开会的时候发布了!我将更新这个问题:SQuestion已更新,是的,缺少一个重载:SHi Servy。我第一次尝试了这种方法。但是,使用表达式仅适用于某些类型。它不适用于DateTime或Nullables,我相信还有一些。您会收到一条错误消息,是关于尝试从DateTime强制转换为对象的。@eyeballpaul您能够支持的唯一方法是为您想要支持的每个参数都有不同的重载。对于动态数量的参数,无法使用不同的泛型参数。老实说,在这一点上,让方法的调用方显式地调用
OrderBy
ThenBy
,而不是试图传递选择器,这样做会更好。您并没有真正为他们节省太多的工作。这更多是因为查询将位于服务层之后,因此前端(MVC)无法进行过滤/排序。我需要做所有的服务。我希望它能适用于所有方面,从分页、排序和过滤。我可以让它的大部分工作良好。剩下的唯一问题(我想)是像我一样的排序described@eyeballpaul在这种情况下,您创建的方法会导致调用者做更多的工作,并且仍然使用LINQ
OrderBy
/
ThenBy
方法。只需完全删除此方法。它增加了负值。让调用方只需调用
GetQuery().OrderBy(o=>o.Whatever)。然后调用by(o=>o.SomethingElse)
。您所描述的方法并不比他们那样做简单/容易,也没有从他们那里抽象出任何东西。服务层位于该层之上,将位于MVC层的另一台服务器上。服务层的返回类似于“IList”。服务层不能返回IEnumerable或IQueryable。服务层将在运行查询时处理,而不是前端。
public List<Order> GetOrders(params Expression<Func<Order, object>>[] selectors)
{
    var dbQuery = GetQuery();

    if (selectors.Any())
    {
        var orderedQuery = dbQuery.OrderBy(selectors.First());

        foreach (var selector in selectors.Skip(1))
            orderedQuery = orderedQuery.ThenBy(selector);
        dbQuery = orderedQuery;
    }

    return dbQuery.ToList();
}