我无法让动态OrderBy在我的通用列表上工作;
var list = CacheObjects.CompetencyAssessments
.Select(x => new CompetencyAssessmentLineViewModel(x))
.ToList();
var sortInfo = string.Format("{0} {1}", request.SortingName, request.SortingOrder);
var displayList = list.AsQueryable()
.OrderBy(sortInfo)
.Skip(startIndex)
.Take(pageLength);
我使用一个字符串来实现OrderBy的动态功能。但是代码无法编译;
错误1方法"System.Linq. queryable . orderby (System.Linq. queryable . order)"的类型参数。不能从用法中推断出IQueryable, System.Linq.Expressions.Expression>)。尝试显式指定类型参数。
我做错了什么?
方法的签名是:
public JsonResult GridData(JqGridRequest request)
和JqGridRequest
来自NuGet包Lib.Web.Mvc
。所以:
-
request.SortingName
是带字段名的字符串, -
request.SortingOrder
为排序顺序
见:http://tpeczek.com/2011/03/jqgrid-and-aspnet-mvc-strongly-typed.html
我怀疑你混淆了IEnumerable和IQueryable与6年前Scott Guthrie提到的动态LINQ库。这是一个必须添加到项目中的外部库。它的最新版本是两年前作为NuGet包发布的。
这个库有一些限制,所以去年Codeplex中出现了另一个System.Linq.Dynamic项目。
这两个库都不是官方支持的LINQ提供程序。如果方便的话,你可以使用它们,但你不应该频繁地更新它们。
实际上,因为你似乎是建立一个ASP。在asp.net MVC应用程序中,在视图或Javascript中对结果进行排序可能比在服务器端进行排序更好。大多数网格允许按列排序。
如果你想为分页目的对结果进行排序,一个更好的选择是使用你的ORM语言,例如Entity SQL for Entity Framework或HQL for NHibernate。
问题是动态库在我的项目中被引用了两次。至少我知道如果类似的事情再次发生应该注意什么了。
正如错误消息告诉您的那样,您正在将string
传递给OrderBy
,而它期望Expression<Func<CompetencyAssessmentLineViewModel, TKey>>
。您需要提供这样一个表达式。
创建字段很难,因为在编译时甚至不知道要排序的字段的类型。这意味着一旦为选择属性生成了正确的表达式,就必须使用反射来调用OrderBy
,因为在编译时不能提供泛型参数。
private static Tuple<Expression, Type> GetSelector<T>(string propertyName)
{
var parameter = Expression.Parameter(typeof(T));
Expression body = Expression.Property(parameter, propertyName);
return Tuple.Create(Expression.Lambda(body, parameter) as Expression
, body.Type);
}
private static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> query,
string property, bool ascending)
{
var selector = GetSelector<T>(property);
Type[] argumentTypes = new[] { typeof(T), selector.Item2 };
var methodName = ascending ? "OrderBy" : "OrderByDescending";
var orderByMethod = typeof(Queryable).GetMethods()
.First(method => method.Name == methodName
&& method.GetParameters().Count() == 2)
.MakeGenericMethod(argumentTypes);
return (IOrderedQueryable<T>)
orderByMethod.Invoke(null, new object[] { query, selector.Item1 });
}
private static IOrderedQueryable<T> ThenBy<T>(IOrderedQueryable<T> query,
string property, bool ascending)
{
var selector = GetSelector<T>(property);
Type[] argumentTypes = new[] { typeof(T), selector.Item2 };
var methodName = ascending ? "ThenBy" : "ThenByDescending";
var orderByMethod = typeof(Queryable).GetMethods()
.First(method => method.Name == methodName
&& method.GetParameters().Count() == 2)
.MakeGenericMethod(argumentTypes);
return (IOrderedQueryable<T>)
orderByMethod.Invoke(null, new object[] { query, selector.Item1 });
}
public static IOrderedQueryable<T> OrderBy<T>(
this IQueryable<T> query,
string property)
{
return OrderBy<T>(query, property, true);
}
public static IOrderedQueryable<T> OrderByDescending<T>(
this IQueryable<T> query,
string property)
{
return OrderBy<T>(query, property, false);
}
public static IOrderedQueryable<T> ThenBy<T>(
this IOrderedQueryable<T> query,
string property)
{
return ThenBy<T>(query, property, true);
}
public static IOrderedQueryable<T> ThenByDescending<T>(
this IOrderedQueryable<T> query,
string property)
{
return ThenBy<T>(query, property, false);
}
现在我们已经准备好了所有基于字符串属性的排序,你可以做你之前想做的事情了:
var displayList = list.OrderBy(request.SortingName)
.ThenBy(request.SortingOrder)
.Skip(startIndex)
.Take(pageLength);