如何在orderby子句中使用LINQ和动态参数

时间:2015-12-12 04:43:04

标签: c# linq linq-to-sql entity-framework-6 iqueryable

我在使用<select name="unittype" required> <option value=""> Select unit type </option> <option value="1"> Miner </option> <option value="2"> Puffer </option> <option value="3"> Snipey </option> <option value="4"> Max </option> <option value="5"> Firebot </option> </select> 表达式

中的动态参数时遇到问题
  1. SearchExp功能

    linq
  2. filterExp功能

    public Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q)
    {
        if (param == "to")
            return e => e.to_msg.Contains(q);
        else if (param == "from")
            return e => e.from_msg.Contains(q);
        else if (param == "cc")
            return e => e.cc_msg.Contains(q);
        else if (param == "bcc")
            return e => e.bcc_msg.Contains(q);
        else if (param == "subject")
            return e => e.subject.Contains(q);
        else
            return e => e.body_text.Contains(q);
    }
    
  3. IQueryable function

       public Expression<Func<EmailAflAwmMessageDM, bool>> FiltertXpr(string filter, string value)
       {
        if (filter == "attachments")
        return e => e.attachments == value;
        else if (filter == "flagged")
        return e => e.flagged == value;
        else
        return e => e.seen == value;
        }
    
  4. 上面的代码正常运行,但我需要动态地 private IQueryable SearchFilter(string param,string q,string filter, string value,string sort,string dir) { var searchXpr = SearchXpr(param, q); var filterXpr = FiltertXpr(filter, value); var emailmessage = db.EmailAflAwmMessage. Where(filterXpr).Where(searchXpr) .OrderByDescending(a => a.msg_date).Select(a => new { a.subject, a.msg_date, }); return emailmessage; } 。 因为我有2个参数排序(意思是它的参数名称)和dir(意思是升序或降序),就像我想要orderby(参数名称)dir 请帮助我,我感谢您宝贵的时间和建议,并建议我以简单的方式替代。感谢。

2 个答案:

答案 0 :(得分:1)

我建议你阅读Expression's tree's,下面的代码是针对didatic的,但我认为这会对你有帮助:

  public static class ExpressionBuilder
    {
        private static readonly MethodInfo ToStringMethod = typeof(object).GetMethod("ToString");
        private static readonly MethodInfo StringContainsMethod = typeof(string).GetMethod("Contains");

        public static Func<T, object> Selector<T>(string prop)
        {
            var type = typeof(T);
            var param = Expression.Parameter(type);
            return Expression.Lambda<Func<T, object>>(Expression.Property(param, type.GetProperty(prop)), param).Compile();
        }

        public static Expression<Func<T, bool>> BuildFilterPredicate<T>(string q)
        {
            var query = Expression.Constant(q);
            var type = typeof(T);
            var lbdSelector = Expression.Parameter(type);
            var predicates = type.GetProperties().SelectMany(p => PredicateContainsBuilder(lbdSelector, p, query)).ToList();
            Expression body = predicates[0];
            body = predicates.Skip(1).Aggregate(body, Expression.OrElse);
            return Expression.Lambda<Func<T, bool>>(body, lbdSelector);
        }

        private static IEnumerable<MethodCallExpression> PredicateContainsBuilder(Expression lbdSelector, PropertyInfo prop, Expression query)
        {

            if (prop.PropertyType.IsClass)
                return new List<MethodCallExpression> { Expression.Call(Expression.Call(Expression.Property(lbdSelector, prop), ToStringMethod), StringContainsMethod, query) };

            var properties = prop.PropertyType.GetProperties();
            return properties.Select(p => Expression.Call(Expression.Call(Expression.Property(lbdSelector, p), ToStringMethod), StringContainsMethod, query)).ToList();
        }
    }

所以现在你用你的方法做到这一点:

  

注意:

     
      
  • 我认为该实体是 EmailMessage 所以我用它来生成谓词;
  •   
  • 它没有深入搜索;
  •   
  • 它会搜索所有属性,并且不会使用string param来定义要匹配的属性;
  •   
private IQueryable SearchFilter(string param,string q,string filter,string value,string sort,string dir)
    {
        var emailMessage = db.EmailAflAwmMessage
                            .Where(ExpressionBuilder.BuildFilterPredicate<EmailMessage>(q))
                            .OrderBy(ExpressionBuilder.Selector<EmailMessage>(sort))
                            .Select(m=> new{m.subject,m.msg_date});        
    return emailmessage;
    }

答案 1 :(得分:1)

我有一个简单的解决方案,现在它与我合作,有更多的选择,但我只是分享我的答案:

  1. SortXpr功能

     private IQueryable SortXpr(IQueryable<EmailAflAwmMessageDM> email ,string sort,string dir) {
    
        if (sort.Contains("to"))
        {
            if (dir.Contains("asc"))
            {
                return email.OrderBy(e => e.to_msg);
            }
            else
            {
                return email.OrderByDescending(e => e.to_msg);
            }
        }
        else if (sort.Contains("from"))
        {
            if (dir.Contains("asc"))
            {
                return email.OrderBy(e => e.from_msg);
            }
            else
            {
                return email.OrderByDescending(e => e.from_msg);
            }
        }
        else if (sort.Contains("subject"))
        {
            if (dir.Contains("asc"))
            {
                return email.OrderBy(e => e.subject);
            }
            else
            {
                return email.OrderByDescending(e => e.subject);
            }
        }
        else
        {
            if (dir.Contains("asc"))
            {
                return email.OrderBy(e => e.msg_date);
            }
            else
            {
                return email.OrderByDescending(e => e.msg_date);
            }
        }
    
    }
    
  2. FilterXpr功能

    private Expression<Func<EmailAflAwmMessageDM, bool>>    FiltertXpr(string filter, string value)
    {
        if (filter == "attachments")
            return e => e.attachments == value;
        else if (filter == "flagged")
            return e => e.flagged == value;
        else
            return e => e.seen == value;
    }
    
  3. SearchXpr功能

    private Expression<Func<EmailAflAwmMessageDM, bool>> SearchXpr(string param, string q)
    {
        if (param == "to")
            return e => e.to_msg.Contains(q);
        else if (param == "from")
            return e => e.from_msg.Contains(q);
        else if (param == "cc")
            return e => e.cc_msg.Contains(q);
        else if (param == "bcc")
            return e => e.bcc_msg.Contains(q);
        else if (param == "subject")
            return e => e.subject.Contains(q);
        else
            return e => e.body_text.Contains(q);
    }
    
  4. SearchFilterCondition函数

     private IQueryable SearchFilterCondition(string param,string q
        ,string filter,string value,string sort,string dir)
     {
       var searchXpr = SearchXpr(param, q);
       var filterXpr = FiltertXpr(filter, value);
       IQueryable<EmailAflAwmMessageDM>
       EmailAflAwmMessagejc = db.EmailAflAwmMessage.Where(filterXpr).Where(searchXpr);
       return SortXpr(EmailAflAwmMessagejc, sort, dir);
     }
    
  5. 感谢stackoverflow社区,感谢您宝贵的时间,再次感谢。