3

具有以下存储变量的变量IQueryable

var mainQuery = session
    .Query<Employee>()
    .Select(e => new
    {
        e.Name,
        e.Address
    });

以及一个将 IQueryable 作为参数的方法。

public DataTable GetData(IQueryable query)
{
    ...
}

我怎样才能在里面写代码GetData()OrderBy()Select()?

的最终值query应该看起来像是使用以下 Linq 表达式构建的:

var query = session
    .Query<Employee>()
    .OrderBy(e => e.Age)
    .Select(e => new
    {
        e.Name,
        e.Address
    });

这是必需的,因为如果我添加OrderBy()之后,Select()我将只能按匿名类型的成员(姓名、地址)进行排序。OrderBy()如果员工也有和年龄,我在放置后无法排序Select()。谢谢你的帮助!

更新:

GetData不知道查询的结构,只是它以 . 结尾Select。而且它必须具有准确的签名public DataTable GetData(IQueryable query)——没有额外的参数。

它需要什么来修改方法内的现有查询并OrderBySelect.

当有正确答案时,我将接受并投票。

4

2 回答 2

3

为什么不只是select()在调用之后应用GetData()

var mainQuery = session.Query<Employee>();

this.GetData(mainQuery);

mainQuery.OrderBy(x => x.Age)
         .Select(x => new
                 {
                     x.Name,
                     x.Address
                 });

Linq 表达式树是不可变的(来源)。您必须分部分创建树的副本才能对其进行修改。

更新:请记住,您的模式试图将数据访问与表示分离(或者至少它是这样读取的)。订购是一个演示问题。您可能有多个客户端想要使用 GetData 来获取数据,但每个客户端都可能希望对数据进行不同的排序。无论如何,您的原始查询是在调用 GetData 之后投影的,因此使用投影进行排序是有意义的。

现在,如果您真的想在方法内部排序而不更改其合同,则必须遍历 linq 查询的表达式树并从头开始重建它,将排序注入正确的位置。表达式树是不可变的,不能就地修改。

于 2013-04-01T15:49:38.073 回答
2

考虑创建ViewModelor DTOforEmployee而不是传递匿名对象。但无论如何,您可以在排序后selector传入并应用它GetDataEmployee

var mainQuery = session.Query<Employee>();

GetData(mainQuery, e => new { e.Name, e.Address });

//object is used because you create anonymous objects and pass them around
public DataTable GetData(IQueryable query, 
                         Expression<Func<Employee, object>> selector)
{
    return query.OrderBy(e => e.Age)
                .Select(selector)
                //...
}
于 2013-04-01T15:52:43.730 回答