我无法让动态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.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
答案 0 :(得分:3)
我怀疑你将IEnumerable和IQueryable混淆了6年前Scott Guthrie提到的Dynamic LINQ库。这是您必须添加到项目中的外部库。其最新版本于2年前发布为a NuGet package。
图书馆有一些限制,去年另一个System.Linq.Dynamic项目出现在Codeplex中。
这两个库都不是官方支持的LINQ提供程序。如果方便,您可以使用它们,但不应经常更新它们。
实际上,由于您似乎正在构建ASP.NET MVC应用程序,因此在视图或Javascript中对结果进行排序可能比在服务器端尝试这样做更好。大多数网格允许按列排序。
如果要对结果进行排序以进行分页,更好的选择是使用ORM的语言来实现,例如Entity SQL for Entity Framework或HQL for NHibernate。
答案 1 :(得分:2)
问题是动态库在我的项目中被引用了两次。至少我知道如果再次发生这样的事情需要注意什么。
答案 2 :(得分:1)
正如错误消息告诉您的那样,您正在将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);