无法使动态OrderBy在我的通用列表上工作



我无法让动态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);

相关内容

  • 没有找到相关文章

最新更新