【问题标题】:adding a generic sorter expression for orderby statements为 orderby 语句添加通用排序器表达式
【发布时间】:2014-03-06 14:30:44
【问题描述】:

(我已将所有代码简化为只有特定问题)

我创建了几个不同的服务方法,它们接受一个排序表达式,我想在 order by 语句中使用它们。

2个版本如下:

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

我打电话给他们:

GetOrders(o => o.CreatedOnDate);
GetOrders2(queryable => queryable.OrderBy(o => o.CreatedOnDate));

如果我只传入某些类型,第一种方法可以正常工作。如果我传入 DateTimeNullable 类型,那么它会抛出一个异常,它不能将这些类型转换为 object

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

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

【问题讨论】:

  • 考虑到您的示例似乎提供了Func&lt;Order, DateTime&gt;,但您的方法采用Func&lt;IQueryable&lt;Order&gt;, IOrderedQueryable&lt;Order&gt;&gt; 类型的参数,即使编译了我也会感到惊讶
  • 这里是否缺少GetOrders 重载?
  • 啊,我需要回到那个方法。我有几个不同的版本,尝试了很多不同的东西,并在我赶去开会时发布!我会更新这个问题:S
  • 问题已更新,是的,缺少重载:S

标签: c# .net linq entity-framework


【解决方案1】:

首先,如果您只想为 GetOrders 提供一个 lambda,那么您需要接受 Expression&lt;Func&lt;Order, object&gt;&gt; 而不是您所拥有的。

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

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

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

【讨论】:

  • 嗨服务。我尝试了这种方法作为我的第一次尝试。但是,使用 Expression> 仅适用于某些类型。它不适用于 DateTime 或 Nullables,我敢肯定还有一些。您会收到一条错误消息,有关尝试将 DateTime 转换为对象的信息。
  • @eyeballpaul 您能够支持的唯一方法是为您希望能够支持的每个参数数量设置不同的重载。对于动态数量的参数,无法使用不同的通用参数。老实说,在这一点上,您最好让方法的调用者显式调用OrderByThenBy,而不是试图只传递选择器。你并没有真正为他们节省很多工作。
  • 更多是因为查询会在服务层后面,所以前端(MVC)不能做过滤/排序。我需要做所有的服务方面。我希望它适用于一切,从分页、排序和过滤。我可以让大部分工作正常。剩下的唯一问题(我认为)是我描述的排序
  • @eyeballpaul 在这种情况下,您创建的方法会导致调用者执行更多工作,并且仍然使用 LINQ OrderBy /ThenBy 方法。只需完全删除此方法。它正在增加负值。让来电者只需拨打GetQuery().OrderBy(o =&gt; o.Whatever).ThenBy(o =&gt; o.SomethingElse)。您所描述的方法并不比他们这样做更简单/容易,也没有从他们那里抽象出任何东西。
  • “GetQuery”在存储库层。服务层位于其之上,并将位于 MVC 层的另一台服务器上。服务层的返回类似于“IList”。服务层不能返回 IEnumerable 或 IQueryable。服务层将在查询运行时处理,而不是前端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-30
  • 2016-06-01
  • 1970-01-01
  • 2018-01-25
  • 2015-04-08
  • 2014-11-06
  • 1970-01-01
相关资源
最近更新 更多