如何在具有IQueryable <t>参数的方法中使用动态linq groupby

时间:2017-01-12 22:53:26

标签: c# linq telerik

您好我有这个现有的代码(现在部分修改),我的任务是替换对telerik网格的依赖(GridCommand参数)。为了避免重复代码,我理解,同事们建议将我的ListCommand添加为可选参数,并修改preparelist方法主体以根据正在使用的指令模型处理分组,排序和过滤操作。我试图按多列分组结果,并计划使用动态linq这样做

data.GroupBy("new(FirstName,GenderId)");

看起来好像没有使用telerik网格参数版本完全实现分组,但现在要求在使用listcommand参数时完全实现分组。

使用以下代码,我如何能够以适合所显示代码的逻辑和返回类型的方式调用groupby的动态linq实现,这需要IQueryable而不是IQueryable?

    public JsonResult newRefreshList(
    ListCommand command,
    int actionId = 0,
    int objectId = 0,
    string parentObjectType = "",
    string relationshipFilter = "",
    ListParameters listParameters = null)
{
    return base.RefreshList<...
}

protected JsonResult RefreshList<T, TContext, THelper>(
    int actionId = 0,
    int objectId = 0,
    ...
{
    try
    {
        ...

        int count = 0;
        var list = LoaderBase<TContext, THelper>.BaseInstance.LoadList<T>(..., null, ref count, listCommand);
        var json = Json(new { Data = list, ...

        return json;
    }
    catch (Exception e)
    {
        ...
    }
}

public virtual IEnumerable LoadList<T>(...)
where T : class
{
    ...
    return listl.GetList<T>(request, gridCommand, ref count, listCommand);
}

public virtual IEnumerable GetList<T>(..., GridCommand gridCommand, ref int count, ListCommand listCommand = null)
    where T : class
{
    try
    {
        using (DataContext) 
        {
            DataContext.Configuration.LazyLoadingEnabled = false;

            DbSet<T> dbSet = DataContext.Set<T>();
            IQueryable<T> qry;
            IQueryable<T> data = null;

            ...

            return PrepareList(gridCommand, data, ref count, listCommand);
        }
    }
    catch (Exception exception)
    {
        throw new Exception("Unable to load the list of entities for type.", exception);
    }
}

public virtual IEnumerable PrepareList<T>(GridCommand gridCommand, IQueryable<T> data, ref int count, ListCommand listCommand = null)
    where T : class
{
    data = CrudHelper.SecurityHelp<T>(data);

    data = this.OrderQuery(data);


    if (gridCommand != null || listCommand != null)
    {
        data = (gridCommand!=null) ? data.ApplyFiltering(gridCommand.FilterDescriptors) : data.ApplyFiltering(listCommand.FilterCriteria);

        ...

        data = (gridCommand != null) ? data.ApplySorting(gridCommand.GroupDescriptors, gridCommand.SortDescriptors): data.ApplySorting(listCommand.SortCriteria);

        var sortedData = data.ToList();
        int page = (gridCommand != null) ? gridCommand.Page : listCommand.Page;
        int pageSize = (gridCommand != null) ? gridCommand.PageSize : listCommand.PageSize;
        sortedData = sortedData.AsEnumerable()
            .ApplyPaging(page, pageSize).ToList();

        return sortedData;
    }
    else
    {
        count = data.Count();
        data = data.ApplyPaging(0, 20);
    }

    return this ...;
}

public static class DynamicQueryable
    {
        ...

        public static IQueryable GroupBy(this IQueryable source, string keySelector, params object[] args)
        {
            if (source == null) throw new ArgumentNullException("source");
            if (keySelector == null) throw new ArgumentNullException("keySelector");

            LambdaExpression keyLambda = DynamicExpression.ParseLambda(source.ElementType, null, keySelector, args);

            return source.Provider.CreateQuery(Expression.Call(
                typeof(Queryable), nameof(Queryable.GroupBy),
                new[] { source.ElementType, keyLambda.Body.Type },
                new[] { source.Expression, Expression.Quote(keyLambda) }));
        }

1 个答案:

答案 0 :(得分:0)

  

我如何能够调用groupby的动态linq实现,这需要IQueryable而不是IQueryable<T>

IQueryable<T>派生自IQueryable,因此您应该可以直接调用此方法:

public static IQueryable GroupBy(this IQueryable source, 
    string keySelector, params object[] args)
{...}

您的评论提问:

  

我认为我的问题是直接在准备清单中打电话   关于IQueryable<T>IQueryable之间隐式转换的方法投诉   GroupBy

是的,它会抱怨,因为您的IQueryable方法会返回IQueryable<T>,但您需要将其用作IQueryable<YourType> after = query.GroupBy( "keySelector", new object[] { } ).Cast<YourType>(); 。因此,您需要这样做:

{{1}}