【问题标题】:Dynamic Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> Expression动态 Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> 表达式
【发布时间】:2013-04-07 05:50:47
【问题描述】:

我正在使用这里提到的模式 http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application

我正在使用下面的方法来查询 EF

public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        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 (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

现在我想创建动态Func&lt;IQueryable&lt;TEntity&gt;, IOrderedQueryable&lt;TEntity&gt;&gt; 表达式来排序我的数据。

我只知道字段名称为字符串,订单类型(升序、降序)为字符串(asc、desc)

【问题讨论】:

  • 这不是通常的订购方式;你见过这个吗? stackoverflow.com/questions/41244/dynamic-linq-orderby
  • @MarcGravell 谢谢,我看到了。但是 MS 的教程包含此代码,因此我正在尝试为此编写合适的动态 LINQ。其实我认为我成功了,但我必须做一些测试,然后让你知道。

标签: c# iqueryable linq-expressions iorderedqueryable


【解决方案1】:

终于可以写出我想要的方法了。

 public static Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> GetOrderBy(string orderColumn, string orderType) {
            Type typeQueryable = typeof(IQueryable<TEntity>);
            ParameterExpression argQueryable = Expression.Parameter(typeQueryable, "p");
            var outerExpression = Expression.Lambda(argQueryable, argQueryable);
            string[] props = orderColumn.Split('.');
            IQueryable<TEntity> query = new List<TEntity>().AsQueryable<TEntity>();
            Type type = typeof(TEntity);
            ParameterExpression arg = Expression.Parameter(type, "x");

            Expression expr = arg;
            foreach(string prop in props) {
                PropertyInfo pi = type.GetProperty(prop, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                expr = Expression.Property(expr, pi);
                type = pi.PropertyType;
            }
            LambdaExpression lambda = Expression.Lambda(expr, arg);
            string methodName = orderType == "asc" ? "OrderBy" : "OrderByDescending";

            MethodCallExpression resultExp =
                Expression.Call(typeof(Queryable), methodName, new Type[] { typeof(TEntity), type }, outerExpression.Body, Expression.Quote(lambda));
            var finalLambda = Expression.Lambda(resultExp, argQueryable);
            return (Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>>)finalLambda.Compile();
        }

这个方法有两个参数,第一个是字段名,另一个是asc或desc。 方法的结果可以直接与 IQueryable 对象一起使用。

感谢您的帮助

【讨论】:

  • 你让我开心。谢谢兄弟。
  • 很高兴听到 5 年后的消息。
【解决方案2】:

聚会已经很晚了,但正确答案位于https://stackoverflow.com/a/10935223/14275的另一个问题上

var students = repository.Get(x => x.FirstName = "Bob",q => q.OrderBy(s => s.LastName));

【讨论】:

    【解决方案3】:

    我不确定您到底想完成什么,但我已经更改了您的代码并添加了一些示例来演示它是如何工作的。

    这是一个简单的控制台应用程序,其中包含 dummyText 作为列表。 Queryable 方法可以根据需要使用过滤器和排序表达式。希望对你有帮助

     class Program
    {
    
        private List<string> _dummyText = new List<string>(){ "Arda",
            "Araba",
            "Antartika",
            "Balon"};
    
        static void Main(string[] args)
        {
            Program p = new Program();
            List<string> result = p.Get(s => s.StartsWith("A"), orderBy: q => q.OrderBy(d => d.Length)).ToList();
    
            Console.ReadLine();
        }
    
    
        public virtual IEnumerable<string> Get(
        Expression<Func<string, bool>> filter = null,
        Func<IQueryable<string>, IOrderedQueryable<string>> orderBy = null)
        {
    
            IQueryable<string> query = _dummyText.AsQueryable();
    
            if (filter != null)
            {
                query = query.Where(filter);
            }
    
            if (orderBy != null)
            {
                return orderBy(query).ToList();
            }
            else
            {
                return query.ToList();
            }
    
    
    
        }
    
    }
    

    【讨论】:

    • 感谢您的回答,但我认为有一些误解。我必须将 z=>z.OrderBy(x=>x.CreatedDate) 发送到 orderBy 参数。所以你的答案在我看来是行不通的。
    • 您可以使用一些外部参数来 linq 表达式,使条件方法执行为内联 if...Ex: string direct = "DESC"; List 结果 = p.Get(s => s.StartsWith("A"), orderBy: q => ((direct == "ASC") ? q.OrderBy(d => d.Length) : q .OrderByDescending(d => d.Length))).ToList();但我怀疑这不是你想要的……
    猜你喜欢
    • 2015-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    相关资源
    最近更新 更多