在现有查询中插入Linq查询部分

本文关键字:Linq 查询部 插入 查询 | 更新日期: 2023-09-27 18:06:45

具有以下存储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
    });

这是必需的,因为如果我在Select()之后添加OrderBy(),我将只能按匿名类型(名称,地址)的成员排序。如果一个员工也有和年龄,当我把OrderBy()放在Select()后面时,我不能按它排序。谢谢你的帮助!

更新:

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

如何修改方法内部的现有查询,并在Select之前添加OrderBy

当有正确答案时,我会接受并投票给它。

在现有查询中插入Linq查询部分

为什么不在调用GetData()之后应用select()呢?

var mainQuery = session.Query<Employee>();
this.GetData(mainQuery);
mainQuery.OrderBy(x => x.Age)
         .Select(x => new
                 {
                     x.Name,
                     x.Address
                 });

Linq表达式树是不可变的(源)。你必须创建一个部分的树的副本来修改它。

Update:请记住,您的模式正在尝试将数据访问与表示分离(或者至少它是如何读取的)。点菜是一种表现方式。您可能有多个客户端希望使用GetData来获取数据,但每个客户端都可能希望对数据进行不同的排序。无论如何,您的原始查询在调用GetData之后投影,因此使用投影排序是有意义的。

现在,如果你真的想在不改变契约的情况下在方法内部排序,你必须遍历linq查询的表达式树,并从头开始重建它,在正确的位置注入排序。表达式树是不可变的,不能就地修改。

考虑为Employee创建ViewModelDTO,并且不传递匿名对象。但无论如何,你可以将selector传递到GetData,并在Employee排序后应用它

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)
                //...
}