我有一个访问数据库的应用程序,必须根据输入按不同的字段对结果进行排序。
这是我的排序功能:
IQueryable<Entity> GetSortedData(IQueryable<Entity> result, String orderby, bool desc)
{
switch (orderby.ToLower())
{
case "id":
result = result.OrderBy(c => c.Id);
break;
case "code":
result = result.OrderBy(c => c.Code);
break;
case "active":
result = result.OrderBy(c => c.Active);
break;
default:
result = result.OrderBy(c => c.Name);
break;
}
if (pageData.SortDesc)
{
var res = result.ToList();
res.Reverse();
return res.AsQueryable();
}
return result;
}
此代码存在一些我不喜欢的问题:
重复的代码太多了。如果它是纯粹的SQL
&#34;查询,它看起来像
SELECT * FROM data_table
订购
CASE @OrderBy
什么时候&#39; id&#39;那么
什么时候编码&#39;然后代码
什么时候活跃&#39;那么活跃
ELSE名称
结束
转换为列表并返回以进行倒车。我无法更改返回类型,我绝对不想编写更多无用的代码(基本上用switch
加倍case
OrderByDescending
。
有人可以提出一些方法来使这个功能更好看,最好还是使用LINQ
吗?
答案 0 :(得分:10)
嗯,你肯定想要使用OrderByDescending
而不是倒车。它不会像SQL一样简短,但你至少可以使用:
IQueryable<Entity> GetSortedData(IQueryable<Entity> result, String orderby, bool desc)
{
switch (orderby.ToLowerInvariant())
{
case "id":
return desc ? result.OrderByDescending(c => c.Id) : result.OrderBy(c => c.Id);
case "code":
return desc ? result.OrderByDescending(c => c.Code) : result.OrderBy(c => c.Code);
case "active":
return desc ? result.OrderByDescending(c => c.Active) : result.OrderBy(c => c.Active);
default:
return desc ? result.OrderByDescending(c => c.Name) : result.OrderBy(c => c.Name);
}
}
您可以使用自己的扩展方法删除重复:
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(
this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
bool descending) =>
descending ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector);
然后写:
IQueryable<Entity> GetSortedData(IQueryable<Entity> result, String orderby, bool desc)
{
switch (orderby.ToLowerInvariant())
{
case "id": return result.OrderBy(c => c.Id, desc);
case "code": return result.OrderBy(c => c.Code, desc);
case "active": return result.OrderBy(c => c.Active, desc);
default: return result.OrderBy(c => c.Name, desc);
}
}
答案 1 :(得分:1)
您可以使用IQueryable的此扩展程序:
using System.Linq.Dynamic;
public static class IQuerableExtensions
{
public static IQueryable<T> ApplySort<T>(this IQueryable<T> source, string sort)
{
if(source == null)
{
throw new ArgumentNullException("source");
}
if(sort == null)
{
return source;
}
var lsSort = sort.Split(',');
// run through the sorting options and create a sort expression string from them
string completeSortExpression = "";
foreach (var sortOption in lsSort)
{
// if the sort option starts with "-", we order descending, otherwise ascending
if(sortOption.StartsWith("-"))
{
completeSortExpression = completeSortExpression + sortOption.Remove(0, 1) + " descending,";
}
else
{
completeSortExpression = completeSortExpression + sortOption + ",";
}
}
if (!string.IsNullOrWhiteSpace(completeSortExpression))
{
source = source.OrderBy(completeSortExpression.Remove(completeSortExpression.Count() - 1));
}
return source;
}
}
要使用它,只需输入:
yourList.AsQueryable().ApplySort("thefieldName")
如果在fieldName之前加上 - ,那么order by将会降序。
yourList.AsQueryable().ApplySort("-thefieldName")
答案 2 :(得分:1)
// this is will work with any class
IQueryable<Entity> GetSortedData(
IQueryable<Entity> result, String orderby, bool desc)
{
return result.OrderBy(orderby, desc);
}
// custom order by extension method
// which will work with any class
public static class QueryableHelper
{
public static IQueryable<TModel> OrderBy<TModel>
(this IQueryable<TModel> q, string name, bool desc)
{
Type entityType = typeof(TModel);
PropertyInfo p = entityType.GetProperty(name);
MethodInfo m = typeof(QueryableHelper)
.GetMethod("OrderByProperty")
.MakeGenericMethod(entityType, p.PropertyType);
return(IQueryable<TModel>) m.Invoke(null, new object[] {
q, p , desc });
}
public static IQueryable<TModel> OrderByProperty<TModel, TRet>
(IQueryable<TModel> q, PropertyInfo p, bool desc)
{
ParameterExpression pe = Expression.Parameter(typeof(TModel));
Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
var exp = Expression.Lambda<Func<TModel, TRet>>(se, pe);
return desc ? q.OrderByDescending(exp) : q.OrderBy(exp);
}
}
答案 3 :(得分:0)
虽然我更喜欢@Jon Skeet提供的强类型方法,但如果你仍然希望以字符串形式进行,你可能会做这样的事情:
public static IQueryable<Entity> Sort(this IQueryable<Entity> collection, string sortBy, bool desc = false)
{
return collection.OrderBy(sortBy + (desc ? " descending" : ""));
}
这需要动态LINQ库,您可以通过
安装install-package System.Linq.Dynamic
答案 4 :(得分:0)
我不确定String orderby
的来源是什么,但如果这是您在代码中指定的内容,那么最好只指定delegate
而不是字符串。这样,您的代码将如下所示
IQueryable<Entity> GetSortedData(IQueryable<Entity> result, Func orderSelector, bool desc) {
return result.OrderBy(orderSelector, desc);
}
就像Jon建议的那样,你可以使用扩展来简化升序和降序。
public static IOrderedQueryable<TSource> OrderBy<TSource, TKey>(
this IQueryable<TSource> source,
Expression<Func<TSource, TKey>> keySelector,
bool desc) =>
desc ? source.OrderByDescending(keySelector) : source.OrderBy(keySelector);
所以,如果你的电话看起来像这样
GetSortedData(result, "Id", true)
现在看起来应该是这样的
GetSortedData(result, (e) => e.Id, true)
PS:有时,从UI控件中选择要排序的字段。在这种情况下,您可以使用他们的.Tag
或类似属性来存储代表。