具有导航属性的Linq动态查询OrderBy

时间:2018-09-20 18:32:38

标签: c# asp.net-mvc entity-framework linq-to-entities

以下是我使用此方法来建立具有分页和排序功能的动态linq查询的方法。但是,当通过与其他实体(例如,实体产品)有关系的属性进行发送排序时,与客户有关系,并且调用获取客户的方法,并且在“ includeProperties”中发送产品,而我希望通过“ Product.Name”进行排序。它没用

方法:

public virtual IEnumerable<TEntity> Get(
            Expression<Func<TEntity, bool>> filter = null,
            Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
            string includeProperties = "", int page = 0, int pagesize = 100, string sortColumn = "", string sortColumnDir = "")
        {
            IQueryable<TEntity> query = dbSet;

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (sortColumn != string.Empty && sortColumn.IndexOf(".") <= 0)
            {
                ParameterExpression[] typeParams = new ParameterExpression[] {
                    Expression.Parameter(typeof(TEntity), "")
                };

                System.Reflection.PropertyInfo pi = typeof(TEntity).GetProperty(sortColumn);

                sortColumnDir = sortColumnDir == "asc" ? "OrderBy" : "OrderByDescending";

                query = (IOrderedQueryable<TEntity>)query.Provider.CreateQuery(
                    Expression.Call(
                        typeof(Queryable),
                        sortColumnDir,
                        new Type[] { typeof(TEntity), pi.PropertyType },
                        query.Expression,
                        Expression.Lambda(Expression.Property(typeParams[0], pi), typeParams))
                );
            }
            else if (orderBy != null)
            {
                query = orderBy(query);
            }
            else
            {
                query = query.OrderBy(obj => obj.Desativado);
            }

            query = query.Skip(page * pagesize).Take(pagesize);

            return query.ToList();
        }

有人可以帮助我吗?

1 个答案:

答案 0 :(得分:0)

当您在"X.Y"参数中传递类似sortColumn的内容时,查询生成器方法会做什么?

首先尝试

if (sortColumn != string.Empty && sortColumn.IndexOf(".") <= 0)

当您在sortColumn中有一个点时,条件的计算结果为false。因此该分支将被跳过。

然后来

else if (orderBy != null)

这不再是成功,您没有提供orderBy,而是提供了sortColumn参数。

所以最后你得到了

else
{
    query = query.OrderBy(obj => obj.Desativado);
}

这显然与您要实现的目标相去甚远,因为它根本无法按X.Y进行排序。

那该怎么办?您必须选择:

  1. 您使用回调而不是路径字符串定义排序:

    ProductRepository.Get(p => p.Name == "X", includeProperties: "Item", orderBy: query => query.OrderBy(product => product.Item.Codigo))
    
  2. 您可以更改查询生成器方法,以使其接受sortColumn中的属性路径。不过,这需要更多的努力。