例如,我想尝试这样的事情。排序参数可能按不同的顺序排列没有,1个或多个排序列。但我无法使用ThenBy
方法,因为它仅在OrderBy
之后才可用。下面的代码将继续将订单重置为排序列表中的最后一项。我也不想改变方法签名。非常感谢帮助,谢谢。
public IQueryable<Person> FilterList(string forename, List<Sorting> sorting)
{
IQueryable<Person> query = dc.Set<Person>();
if(!string.IsNullOrEmpty(forename)){
query = query.Where(w=>w.Forename.Contains(forename));
foreach(var sort in sorting)
{
switch(sort.By)
{
case "asc":
switch(sort.Sort)
{
case "forename":
query = query.OrderBy(o=>o.Forename);
break;
case "surname":
query = query.OrderBy(o=>o.Surname);
break;
}
break;
case "desc":
switch(sort.Sort)
{
case "forename":
query = query.OrderByDescending(o=>o.Forename);
break;
case "surname":
query = query.OrderByDescending(o=>o.Surname);
break;
}
break;
}
}
return query;
}
public class Sorting
{
public string Sort{get;set;}
public string By{get;set;}
}
答案 0 :(得分:3)
AgentFire的答案实际上是合适的,但在每种情况下对特殊情况都有点啰嗦。我添加了一个扩展方法:
编辑:显然,下面的代码没有正确确定查询是否已经订购;甚至无序版本显然也实现了IOrderedQueryable<T>
。使用source.Expression.Type
检查IOrderedQueryable<T>
显然有效,但我已将此代码留在此处作为更多逻辑方法 - 并且正如此&#34;修复&#34 ;听起来比我更喜欢用我的名字回答:)
public static IOrderedQueryable<T> AddOrdering<T, TKey>(
this IQueryable<T> source,
Expression<Func<T, TKey>> keySelector,
bool descending)
{
IOrderedQueryable<T> ordered = source as IOrderedQueryable<T>;
// If it's not ordered yet, use OrderBy/OrderByDescending.
if (ordered == null)
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
// Already ordered, so use ThenBy/ThenByDescending
return descending ? ordered.ThenByDescending(keySelector)
: ordered.ThenBy(keySelector);
}
然后你的主叫代码变成:
foreach(var sort in sorting)
{
bool descending = sort.By == "desc";
switch (sort.Sort)
{
case "forename":
query = query.AddOrdering(o => o.Forename, descending);
break;
case "surname":
query = query.AddOrdering(o => o.Surname, descending);
break;
}
}
这样,每个额外的排序选项只会增加很少的代码开销。
答案 1 :(得分:1)
您可能想要使用演员:
var sortedQueryable = query as IOrderedQueryable<Person>;
if (sortedQueryable != null)
{
query = sortedQueryable.ThenBy(o => o.Forename);
}
else
{
query = query.OrderBy(o => o.Forename);
}
在每次迭代中都会这样做。
另外,我会将魔术字符串“asc”和“desc”更改为enum(如enum SortMode
)和List<Sorting>
参数:
List<Tuple<Expression<Func<Person, object>>, SortMode>> parameter;
因此,在foreach
循环中,您只需要if
SortMode
并将Item2
元组传递给订购者。
答案 2 :(得分:0)
首先按常量排序,因此您有一个IOrderedQueryable<T>
,然后您可以通过ThenBy
方法完成所有自定义排序。
public IQueryable<Person> FilterList(string forename, List<Sorting> sorting) {
IQueryable<Person> query = dc.Set<Person>();
if(!string.IsNullOrEmpty(forename)){
query = query.Where(w=>w.Forename.Contains(forename));
var orderedQuery = query.OrderBy(x => 1);
foreach(var sort in sorting) {
switch(sort.By) {
case "asc":
switch(sort.Sort) {
case "forename":
orderedQuery = orderedQuery.ThenBy(o=>o.Forename);
break;
case "surname":
orderedQuery = orderedQuery.ThenBy(o=>o.Surname);
break;
}
break;
case "desc":
switch(sort.Sort) {
case "forename":
orderedQuery = orderedQuery.ThenByDescending(o=>o.Forename);
break;
case "surname":
orderedQuery = orderedQuery.ThenByDescending(o=>o.Surname);
break;
}
break;
}
}
return orderedQuery;
}
答案 3 :(得分:0)
这是我正在使用,试用和测试的代码。基于Jon Skeets的解决方案,归功于他,我只是为了我的目的而调整。
public static IOrderedQueryable<T> AddOrdering<T, TKey>(
this IQueryable<T> source,
Expression<Func<T, TKey>> keySelector,
bool descending)
{
// If it's not ordered yet, use OrderBy/OrderByDescending.
if(source.Expression.Type != typeof(IOrderedQueryable<T>))
{
return descending ? source.OrderByDescending(keySelector)
: source.OrderBy(keySelector);
}
// Already ordered, so use ThenBy/ThenByDescending
return descending ? ((IOrderedQueryable<T>)source).ThenByDescending(keySelector)
: ((IOrderedQueryable<T>)source).ThenBy(keySelector);
}
然后你的主叫代码变成:
foreach(var sort in sorting)
{
bool descending = sort.By == "desc";
switch (sort.Sort)
{
case "forename":
query = query.AddOrdering(o => o.Forename, descending);
break;
case "surname":
query = query.AddOrdering(o => o.Surname, descending);
break;
}
}
答案 4 :(得分:-1)
有很多选择可以做到。例如:
bool isSorted = false;
foreach(var sort in sorting)
{
switch(sort.By)
{
case "asc":
switch(sort.Sort)
{
case "forename":
if (!isSorted)
{
query = query .OrderBy(o => o.Forename);
isSorted = true;
}
else
{
query = ((IOrderedQueryable<Person>)query).ThenBy(o => o.Forename);
}
...
}
break;
case "desc":
...
}
}
修改强>
感谢AgentFire
指出我的错误。