Expression<Func<T>>和Func<T>

简介:   以前用EF的时候,由于where的时候有Expression和Func两种查询条件,误用了Func那个重载,后来还想通过func创建查询来着,不过失败了,导致了全表查询,真是无语.国内的人答的比较言简意赅(其实我觉得讲的不好).

 

  以前用EF的时候,由于where的时候有Expression<Func<T>>和Func<T>两种查询条件,误用了Func<T>那个重载,后来还想通过func创建查询来着,不过失败了,导致了全表查询,真是无语.国内的人答的比较言简意赅(其实我觉得讲的不好).还是老外讲的明白点.

  翻译过来吧,就是说Func<T>是方法的委托,而Expression<Func<T>>是拉姆达表达式树.这个树状结构描述了各种各样恶心的参数(如下图所示).我们可以用Expression.Compile做成一个委托或者编译成sql(EF).  

Expression<Func<int>> myExpression = () => 10;

  其实吧, 多用一下你就知道了.Func<T>用的还蛮多的,当时就是用来运行泛化的方法的,而Expression<Func<T>>用在动态查询拼接的时候比较多,比如 (And和or,拼接多条表达式树).

 

public static class PredicateBuilder
    {
        public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
        {
            return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.And));
        }

        private static Expression<Func<T, bool>> Compose<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second, Func<Expression, Expression, Expression> merge)
        {
            Expression expression = new ParameterRebinder(second.Parameters[0], first.Parameters[0]).Visit(second.Body);
            return Expression.Lambda<Func<T, bool>>(merge(first.Body, expression), first.Parameters);
        }

        public static Expression<Func<T, bool>> False<T>()
        {
            return item => false;
        }

        public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> predicate)
        {
            return Expression.Lambda<Func<T, bool>>(Expression.Not(predicate.Body), predicate.Parameters);
        }

        public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
        {
            return first.Compose<T>(second, new Func<Expression, Expression, Expression>(Expression.Or));
        }

        public static Expression<Func<T, bool>> True<T>()
        {
            return item => true;
        }

        private sealed class ParameterRebinder : ExpressionVisitor
        {
            private readonly ParameterExpression m_From;
            private readonly ParameterExpression m_To;

            public ParameterRebinder(ParameterExpression from, ParameterExpression to)
            {
                this.m_From = from;
                this.m_To = to;
            }

            protected override Expression VisitParameter(ParameterExpression node)
            {
                if (node == this.m_From)
                {
                    node = this.m_To;
                }
                return base.VisitParameter(node);
            }
        }



    }

  

表达式树恶心的地方,我写一个orderby给你看看.

        public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
        {
            string command = desc ? "OrderByDescending" : "OrderBy";
            var type = typeof(TEntity);//实体的类型
            var property = type.GetProperty(orderByProperty);
            var parameter = Expression.Parameter(type, "o");
            var propertyAccess = Expression.MakeMemberAccess(parameter, property);
            var orderByExpression = Expression.Lambda(propertyAccess, parameter);
            var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType },
                                          source.Expression, Expression.Quote(orderByExpression));
            return source.Provider.CreateQuery<TEntity>(resultExpression);
        }

  动态linq是需要反射的.而且这种写法不利于调试.因为你特么完全不知道生成的什么鬼,除非你对这玩意真的很熟.好吧,你赢了.

 

参考链接:

Why would you use Expression<Func<T>> rather than Func<T>?

Entity Framework - Func引起的数据库全表查询

通过已有Func构造Expression表达式问题

目录
相关文章
|
3月前
bpf_func_id是如何产生的?
bpf_func_id是如何产生的?
|
7月前
|
C语言 C++
关于内部函数(Static Functions)的文章
关于内部函数(Static Functions)的文章
52 1
|
7月前
|
JavaScript 前端开发
call函数和apply函数的区别
call函数和apply函数的区别
56 0
|
安全
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
344 0
VS2019 error C4996: ‘scanf‘: This function or variable may be unsafe 错误
Java类Demo中存在方法func1、func2、func3和func4,请问该方法中,哪些是不合法的定义?( )
Java类Demo中存在方法func1、func2、func3和func4,请问该方法中,哪些是不合法的定义?( )
|
Web App开发 JavaScript 前端开发
从规范去看Function.prototype.call到底是怎么工作的?
从规范去看Function.prototype.call到底是怎么工作的?
从规范去看Function.prototype.call到底是怎么工作的?
宏"__FUNCTION__" 和" __LINE__ "
宏"__FUNCTION__" 和" __LINE__ "
262 0
ES6 箭头函数: () => {} 与匿名函数 function() {}
function foo() { setTimeout( () => { console.log("id:", this.id); },100); } foo.
1580 0