排序依据LAMBDA的泛型列表(Generic List of OrderBy Lambda)

2019-09-21 06:28发布

我想建立一个通用的查询机制来访问我的仓库。 我想用Lambda表达式过滤和排序的查询。 我在努力寻找一种方式来传递在通用Lambda表达式的列表,专门针对订单的,并会在这样欣赏的帮助。

编辑:2级的要求,我想满足的,没有暴露的IQueryable超越资源库,但仍然能够进行一些过滤,并在数据库级排序。

为了更好地说明这一点让我告诉你的代码

public class Query<T>
{
    public class OrderBy<T>
    {
        public Expression<Func<T, **int**>> Clause { set; get; } // Order By clause
        public bool Descending = true;
    }

    public Expression<Func<T, bool>> Where { set; get; } // Where clause
    public IList<OrderBy<T>> OrderBys { set; get; } // Where clause

    public Query()
    {
        OrderBys = new List<OrderBy<T>>();
    }
}    

public IEnumerable<Person> FindBy(Query<Person> query)
{
    IQueryable<Person> Temp = GetObjectSet();
    if (query.Where != null) 
        Temp = Temp.Where(query.Where);
    foreach (var OrderByThis in query.OrderBys)
    {
        if (OrderByThis.Descending) 
            Temp = Temp.OrderByDescending(OrderByThis.Clause);
        else 
            Temp = Temp.OrderBy(OrderByThis.Clause);
    }

    return Temp.ToList<Person>();
}

这是非常好的,但表达<Func键<T,INT >>是不通用的。 我需要能够做的是这样的:

Query<Person> query = new Query<Person>();
Query<Person>.OrderBy<Person> clause1 = new Query<Person>.OrderBy<Person>();
clause1.Clause = m => m.Username;
Query<Person>.OrderBy<Person> clause2 = new Query<Person>.OrderBy<Person>();
clause2.Clause = m => m.DateOfBirth;
query.OrderBys.Add(clause1);
query.OrderBys.Add(clause2);

即加入了许多不同类型的不同字段。

我想必须有这些存储为通用lambda函数的方式,然后在仓库中,然后转换成需要的强类型的lambda函数。

我怎样才能做到这一点?

Answer 1:

正如我在答复中指出,以您的其他问题 ,我会劝阻一般这种方法。 更有意义只是以暴露IQueryable<T> / IOrderedQueryable<T>

话虽这么说,沿着你打算在选定的答案可用的线路解决如何将多个表达式传递给排序依据为EF? 。

它可以让你使用的语法,如:

var query = context.Users ... ;

var queryWithOrderBy = ApplyOrderBy(query,
    new OrderByExpression<User, string>(expression: u => u.UserName, descending: false),    // a string, asc
    new OrderByExpression<User, int>(expression: u => u.UserId, descending: true));  // an int, desc

var result = queryWithOrderBy.ToList(); // didn't throw an exception for me


Answer 2:

在阐述我的意见,我不明白为什么你需要从中间对象,当你可以只跳过翻译共建自己的中间查询对象的表达出来,然后重建表达式。

鉴于您的示例查询:

repository.FindBy(people => people.OrderBy(p => p.Username).ThenBy(p => p.DateOfBirth));

注意,你仍然可以建立查询增量,如果根据用户的选择正在做它,例如。 下面的查询是相当于上面:

Func<IEnumerable<Person>, IEnumerable<Person>> query = people => people.OrderBy(p => p.Username);
 query = query.ThenBy(p => p.DateOfBirth);

我知道你不想暴露IQueryable超越库,但是你仍然可以使用LINQ与签名,例如:

public IEnumerable<Person> FindBy(Func<IEnumerable<Person>, IEnumerable<Person>> query)
{
    return query(GetObjectSet()).ToList();
}

说起你的实际问题,但是,你可以实现你的OrderBy使用任务Expression<Func<T, object>>Clause属性类型,或者如果你搅乱,你可以多一点利用约束它IComparable ,而不是对象,因为它实际上是所有你需要订购,并且字符串和数字类型都实现了。



文章来源: Generic List of OrderBy Lambda