Ejemplo n.º 1
0
        /// <summary>
        /// 创建 SQL 命令
        /// </summary>
        /// <param name="dbQueryable">查询 语句</param>
        /// <param name="indent">缩进</param>
        /// <param name="isOuter">是否最外层,内层查询不需要结束符(;)</param>
        /// <param name="token">解析上下文参数</param>
        /// <returns></returns>
        public Command Resolve <T>(IDbQueryable <T> dbQueryable, int indent, bool isOuter, ResolveToken token)
        {
            // 设置该查询是否需要参数化
            if (token == null)
            {
                token = new ResolveToken();
            }
            if (!((DbQueryable)dbQueryable).HasSetParameterized)
            {
                dbQueryable.Parameterized = true;
            }
            if (dbQueryable.Parameterized && token.Parameters == null)
            {
                token.Parameters = new List <IDbDataParameter>(8);
            }

            // 调试模式
            if (token != null && !token.HasSetIsDebug)
            {
                token.IsDebug = dbQueryable.DbContext.IsDebug;
            }

            // 解析查询语义
            IDbQueryableInfo <T> dbQueryInfo = DbQueryParser.Parse(dbQueryable);

            DbQueryableInfo_Select <T> sQueryInfo = dbQueryInfo as DbQueryableInfo_Select <T>;

            if (sQueryInfo != null)
            {
                return(this.ParseSelectCommand <T>(sQueryInfo, indent, isOuter, token));
            }

            DbQueryableInfo_Insert <T> nQueryInfo = dbQueryInfo as DbQueryableInfo_Insert <T>;

            if (nQueryInfo != null)
            {
                return(this.ParseInsertCommand <T>(nQueryInfo, token));
            }

            DbQueryableInfo_Update <T> uQueryInfo = dbQueryInfo as DbQueryableInfo_Update <T>;

            if (uQueryInfo != null)
            {
                return(this.ParseUpdateCommand <T>(uQueryInfo, token));
            }

            DbQueryableInfo_Delete <T> dQueryInfo = dbQueryInfo as DbQueryableInfo_Delete <T>;

            if (dQueryInfo != null)
            {
                return(this.ParseDeleteCommand <T>(dQueryInfo, token));
            }

            throw new NotImplementedException();
        }
Ejemplo n.º 2
0
        /// <summary>
        /// 创建 SQL 命令
        /// </summary>
        /// <param name="dbQuery">查询 语句</param>
        /// <param name="indent">缩进</param>
        /// <param name="isOuter">是否最外层,内层查询不需要结束符(;)</param>
        /// <param name="token">解析上下文参数</param>
        /// <returns></returns>
        public Command Resolve <T>(IDbQueryable <T> dbQuery, int indent, bool isOuter, ResolveToken token)
        {
            // 设置该查询是否需要参数化
            if (token == null)
            {
                token = new ResolveToken();
            }
            if (!((DbQueryable)dbQuery).HasSetParameterized)
            {
                dbQuery.Parameterized = true;
            }
            if (dbQuery.Parameterized && token.Parameters == null)
            {
                token.Parameters = new List <IDbDataParameter>(8);
            }

            // 调试模式
            if (token != null && !token.HasSetIsDebug)
            {
                token.IsDebug = dbQuery.DbContext.IsDebug;
            }

            // 解析查询语义
            IDbQueryableInfo <T> result = DbQueryParser.Parse(dbQuery);
            // 查询
            DbQueryableInfo_Select <T> result_Query = result as DbQueryableInfo_Select <T>;

            if (result_Query != null)
            {
                return(this.ResolveSelectCommand <T>(result_Query, indent, isOuter, token));
            }
            // 新增
            DbQueryableInfo_Insert <T> result_Insert = result as DbQueryableInfo_Insert <T>;

            if (result_Insert != null)
            {
                return(this.ResolveInsertCommand <T>(result_Insert, token));
            }
            // 更新
            DbQueryableInfo_Update <T> result_Update = result as DbQueryableInfo_Update <T>;

            if (result_Update != null)
            {
                return(this.ResolveUpdateCommand <T>(result_Update, token));
            }
            // 删除
            DbQueryableInfo_Delete <T> result_Delete = result as DbQueryableInfo_Delete <T>;

            if (result_Delete != null)
            {
                return(this.ResolveDeleteCommand <T>(result_Delete, token));
            }

            throw new NotImplementedException();
        }
Ejemplo n.º 3
0
        /// <summary>
        /// 创建 SQL 命令
        /// </summary>
        /// <param name="dbQueryable">查询 语句</param>
        /// <param name="indent">缩进</param>
        /// <param name="isOuter">是否最外层,内层查询不需要结束符(;)</param>
        /// <param name="parameters">已存在的参数列表</param>
        /// <returns></returns>
        public DbCommandDefinition Resolve <T>(IDbQueryable <T> dbQueryable, int indent = 0, bool isOuter = true, List <IDbDataParameter> parameters = null)
        {
            // 设置该查询是否需要参数化
            if (!((DbQueryable)dbQueryable).HasSetParameterized)
            {
                dbQueryable.Parameterized = true;
            }
            if (dbQueryable.Parameterized && parameters == null)
            {
                parameters = new List <IDbDataParameter>(8);
            }

            // 解析查询语义
            IDbQueryableInfo <T> info = DbQueryParser.Parse(dbQueryable);

            DbQueryableInfo_Select <T> sQuery = info as DbQueryableInfo_Select <T>;

            if (sQuery != null)
            {
                return(this.ParseSelectCommand <T>(sQuery, indent, isOuter, dbQueryable.Parameterized ? parameters : null));
            }

            DbQueryableInfo_Insert <T> nQuery = info as DbQueryableInfo_Insert <T>;

            if (nQuery != null)
            {
                return(this.ParseInsertCommand <T>(nQuery, dbQueryable.Parameterized ? parameters : null));
            }

            DbQueryableInfo_Update <T> uQuery = info as DbQueryableInfo_Update <T>;

            if (uQuery != null)
            {
                return(this.ParseUpdateCommand <T>(uQuery, dbQueryable.Parameterized ? parameters : null));
            }

            DbQueryableInfo_Delete <T> dQuery = info as DbQueryableInfo_Delete <T>;

            if (dQuery != null)
            {
                return(this.ParseDeleteCommand <T>(dQuery, dbQueryable.Parameterized ? parameters : null));
            }

            throw new NotImplementedException();
        }
Ejemplo n.º 4
0
        // 获取 JOIN 子句关联表的的别名
        protected TableAliasCache PrepareAlias <T>(DbQueryableInfo_Select <T> query, ResolveToken token)
        {
            TableAliasCache aliases = new TableAliasCache((query.Joins != null ? query.Joins.Count : 0) + 1, token != null ? token.TableAliasName : null);

            foreach (DbExpression exp in query.Joins)
            {
                // [INNER/LEFT JOIN]
                if (exp.DbExpressionType == DbExpressionType.GroupJoin || exp.DbExpressionType == DbExpressionType.Join || exp.DbExpressionType == DbExpressionType.GroupRightJoin)
                {
                    this.PrepareLfInJoinAlias(exp, aliases);
                }
                else if (exp.DbExpressionType == DbExpressionType.SelectMany)
                {
                    this.PrepareCrossJoinAlias(exp, aliases);
                }
            }

            return(aliases);
        }
Ejemplo n.º 5
0
        // 构造由一对多关系产生的嵌套查询
        static DbQueryableInfo_Select <TElement> TryBuildOutQuery <TElement>(DbQueryableInfo_Select <TElement> sQueryInfo)
        {
            // @havePaging 是否有分页信息

            if (sQueryInfo == null || sQueryInfo.SelectExpression == null)
            {
                return(sQueryInfo);
            }

            Expression          select  = sQueryInfo.SelectExpression.Expressions[0];
            List <DbExpression> include = sQueryInfo.Includes;
            Type type = sQueryInfo.FromType;

            // 解析导航属性 如果有 1:n 的导航属性,那么查询的结果集的主记录将会有重复记录
            // 这时就需要使用嵌套语义,先查主记录,再关联导航记录
            Expression expression       = select;
            var        lambdaExpression = expression as LambdaExpression;

            if (lambdaExpression != null)
            {
                expression = lambdaExpression.Body;
            }
            var initExpression = expression as MemberInitExpression;
            var newExpression  = expression as NewExpression;

            bool hasManyNavgation = CheckManyNavigation(include);

            if (!hasManyNavgation)
            {
                hasManyNavgation = initExpression != null && CheckManyNavigation <TElement>(initExpression);
            }

            #region 嵌套语义

            if (hasManyNavgation)
            {
                newExpression = initExpression != null ? initExpression.NewExpression : newExpression;
                List <MemberBinding> bindings = new List <MemberBinding>();
                if (initExpression != null)
                {
                    bindings = initExpression.Bindings.ToList(x => x, x => TypeUtils.IsPrimitiveType((x.Member as System.Reflection.PropertyInfo).PropertyType));
                }

                if (newExpression != null || bindings.Count() > 0)
                {
                    // 简化内层选择器,只选择最小字段,不选择导航字段,导航字段在外层加进去
                    initExpression              = Expression.MemberInit(newExpression, bindings);
                    lambdaExpression            = Expression.Lambda(initExpression, lambdaExpression.Parameters);
                    sQueryInfo.SelectExpression = new DbExpression(DbExpressionType.Select, lambdaExpression);
                }
                sQueryInfo.ResultByManyNavigation = true;
                sQueryInfo.Includes = new List <DbExpression>(0);

                var outQueryInfo = new DbQueryableInfo_Select <TElement>();
                outQueryInfo.FromType          = type;
                outQueryInfo.SubQueryInfo      = sQueryInfo;
                outQueryInfo.Joins             = new List <DbExpression>(0);
                outQueryInfo.OrderBys          = new List <DbExpression>(0);
                outQueryInfo.Includes          = include;
                outQueryInfo.HasManyNavigation = true;
                outQueryInfo.SelectExpression  = new DbExpression(DbExpressionType.Select, select);

                #region 排序

                if (sQueryInfo.OrderBys.Count > 0)
                {
                    // 是否有分页
                    bool havePaging = (sQueryInfo.Take > 0 || sQueryInfo.Skip > 0);
                    if (!havePaging)
                    {
                        // 如果没有分页,则OrderBy需要放在外层
                        outQueryInfo.OrderBys = sQueryInfo.OrderBys;
                        sQueryInfo.OrderBys   = new List <DbExpression>(0);
                    }
                    else
                    {
                        // 如果有分页,只有主表/用到的1:1从表放在内层,其它放在外层
                        List <DbExpression> innerOrderBy = null;
                        foreach (var dbExpression in sQueryInfo.OrderBys)
                        {
                            hasManyNavgation = CheckManyNavigation(dbExpression.Expressions[0] as LambdaExpression);
                            if (!hasManyNavgation)
                            {
                                if (innerOrderBy == null)
                                {
                                    innerOrderBy = new List <DbExpression>();
                                }
                                innerOrderBy.Add(dbExpression);
                            }
                        }

                        if (innerOrderBy != null && innerOrderBy.Count > 0)
                        {
                            outQueryInfo.OrderBys = sQueryInfo.OrderBys;
                            sQueryInfo.OrderBys   = innerOrderBy;
                        }
                    }
                }

                #endregion

                #region 分组

                if (sQueryInfo.GroupByExpression != null)
                {
                    // 查看外层是否需要重新构造选择器。如果有分组并且有聚合函数,则需要重新构造选择器。否则外层解析不了聚合函数
                    // demo => line 640
                    bool newSelector = bindings.Any(x => ((MemberAssignment)x).Expression.NodeType == ExpressionType.Call) || newExpression.Arguments.Any(x => x.NodeType == ExpressionType.Call);
                    if (newSelector)
                    {
                        ParameterExpression newParameter  = null;
                        List <DbExpression> dbExpressions = null;
                        if (outQueryInfo.Includes != null && outQueryInfo.Includes.Count > 0)
                        {
                            dbExpressions = outQueryInfo.Includes;
                        }
                        else if (outQueryInfo.OrderBys != null && outQueryInfo.OrderBys.Count > 0)
                        {
                            dbExpressions = outQueryInfo.OrderBys;
                        }
                        if (dbExpressions != null && dbExpressions.Count > 0)
                        {
                            newParameter = (dbExpressions[0].Expressions[0] as LambdaExpression).Parameters[0];
                        }

                        // 1对多导航嵌套查询外层的的第一个表别名固定t0,参数名可随意
                        var parameterExpression = newParameter != null ? newParameter : Expression.Parameter(newExpression.Type, "__g");
                        bindings = bindings.ToList(x => (MemberBinding)Expression.Bind(x.Member, Expression.MakeMemberAccess(parameterExpression, x.Member)));
                        List <Expression> arguments = null;
                        if (newExpression.Members != null)
                        {
                            arguments = new List <Expression>(newExpression.Arguments.Count);
                            for (int i = 0; i < newExpression.Arguments.Count; i++)
                            {
                                var member = newExpression.Members[i];
                                var arg    = Expression.MakeMemberAccess(parameterExpression, member);
                                arguments.Add(arg);
                            }
                        }

                        newExpression    = Expression.New(newExpression.Constructor, arguments, newExpression.Members);
                        initExpression   = Expression.MemberInit(newExpression, bindings);
                        lambdaExpression = Expression.Lambda(initExpression, parameterExpression);
                        outQueryInfo.SelectExpression = new DbExpression(DbExpressionType.Select, lambdaExpression);
                    }
                }

                #endregion

                sQueryInfo = outQueryInfo;
            }

            #endregion

            return(sQueryInfo);
        }
Ejemplo n.º 6
0
        // 解析查询语义
        static IDbQueryableInfo <TElement> Parse <TElement>(IDbQueryable <TElement> dbQuery, int startIndex)
        {
            // 目的:将query 转换成增/删/改/查
            // 1、from a in context.GetTable<T>() select a 此时query里面可能没有SELECT 表达式
            // 2、Take 视为一个查询的结束位,如有更多查询,应使用嵌套查询
            // 3、uion 分页查询也使嵌套语义
            // 4、uion 后面跟着 WHERE,GROUP BY,SELECT,JOIN语句时需要使用嵌套查询

            Type type              = null;
            bool isDistinct        = false;
            bool isAny             = false;
            bool subQuery          = false;
            int? skip              = null;
            int? take              = null;
            int? outerIndex        = null;
            var  whereExpressions  = new List <Expression>();   // WHERE
            var  havingExpressions = new List <Expression>();   // HAVING
            var  joins             = new List <DbExpression>(); // JOIN
            var  orderBys          = new List <DbExpression>(); // ORDER BY
            var  includes          = new List <DbExpression>(); // ORDER BY
            var  unions            = new List <IDbQueryableInfo <TElement> >();

            Expression   selectExpression  = null;            // SELECT #
            DbExpression insertExpression  = null;            // INSERT #
            DbExpression updateExpression  = null;            // UPDATE #
            DbExpression deleteExpression  = null;            // DELETE #
            DbExpression groupByExpression = null;            // GROUP BY #
            DbExpression statisExpression  = null;            // SUM/MAX  #

            for (int index = startIndex; index < dbQuery.DbExpressions.Count; index++)
            {
                DbExpression curExpr = dbQuery.DbExpressions[index];

                // Take(n)
                if (take != null || (skip != null && curExpr.DbExpressionType != DbExpressionType.Take) || isDistinct || subQuery)
                {
                    outerIndex = index;
                    break;
                }

                #region 解析片断

                switch (curExpr.DbExpressionType)
                {
                case DbExpressionType.None:
                case DbExpressionType.All:
                    continue;

                case DbExpressionType.Any:
                    isAny = true;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    break;

                case DbExpressionType.AsSubQuery:
                    subQuery = true;
                    continue;

                case DbExpressionType.Union:
                    var uQuery = (curExpr.Expressions[0] as ConstantExpression).Value as IDbQueryable <TElement>;
                    var u      = DbQueryParser.Parse(uQuery);
                    unions.Add(u);

                    // 如果下一个不是 union,就使用嵌套
                    if (index + 1 <= dbQuery.DbExpressions.Count - 1 && dbQuery.DbExpressions[index + 1].DbExpressionType != DbExpressionType.Union)
                    {
                        subQuery = true;
                    }
                    continue;

                case DbExpressionType.Include:
                    includes.Add(curExpr);
                    continue;

                case DbExpressionType.GroupBy:
                    groupByExpression = curExpr;
                    continue;

                case DbExpressionType.GetTable:
                    type = (curExpr.Expressions[0] as ConstantExpression).Value as Type;
                    continue;

                case DbExpressionType.Average:
                case DbExpressionType.Min:
                case DbExpressionType.Sum:
                case DbExpressionType.Max:
                    statisExpression = curExpr;
                    continue;

                case DbExpressionType.Count:
                    statisExpression = curExpr;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.GroupJoin:
                case DbExpressionType.GroupRightJoin:
                    selectExpression = curExpr.Expressions[3];
                    joins.Add(curExpr);
                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    orderBys.Add(curExpr);
                    continue;

                case DbExpressionType.Select:
                    selectExpression = curExpr.Expressions != null ? curExpr.Expressions[0] : null;
                    continue;

                case DbExpressionType.SelectMany:
                    selectExpression = curExpr.Expressions[1];
                    if (CheckSelectMany(dbQuery.DbExpressions, curExpr, startIndex))
                    {
                        joins.Add(curExpr);
                    }
                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        whereExpressions.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Skip:
                    skip = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.Take:
                    take = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.ThenBy:
                case DbExpressionType.ThenByDescending:
                    orderBys.Add(curExpr);
                    continue;

                case DbExpressionType.Where:
                    var predicate = groupByExpression == null ? whereExpressions : havingExpressions;
                    if (curExpr.Expressions != null)
                    {
                        predicate.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Insert:
                    insertExpression = curExpr;
                    continue;

                case DbExpressionType.Update:
                    updateExpression = curExpr;
                    continue;

                case DbExpressionType.Delete:
                    deleteExpression = curExpr;
                    continue;

                default:
                    throw new NotSupportedException(string.Format("{0} is not support.", curExpr.DbExpressionType));
                }

                #endregion
            }

            // 没有解析到INSERT/DELETE/UPDATE/SELECT表达式,并且没有相关统计函数,则默认选择FromType的所有字段
            bool useFullFields = insertExpression == null && deleteExpression == null && updateExpression == null && selectExpression == null && statisExpression == null;
            if (useFullFields)
            {
                selectExpression = Expression.Constant(type ?? typeof(TElement));
            }

            var sQueryInfo = new DbQueryableInfo_Select <TElement>();
            sQueryInfo.FromType          = type;
            sQueryInfo.HaveDistinct      = isDistinct;
            sQueryInfo.HaveAny           = isAny;
            sQueryInfo.Joins             = joins;
            sQueryInfo.OrderBys          = orderBys;
            sQueryInfo.GroupByExpression = groupByExpression;
            sQueryInfo.StatisExpression  = statisExpression;
            sQueryInfo.Unions            = unions;
            sQueryInfo.Includes          = includes;
            sQueryInfo.Skip             = skip != null ? skip.Value : 0;
            sQueryInfo.Take             = take != null ? take.Value : 0;
            sQueryInfo.SelectExpression = new DbExpression(DbExpressionType.Select, selectExpression);
            sQueryInfo.WhereExpression  = new DbExpression(DbExpressionType.Where, CombineWhere(whereExpressions));
            sQueryInfo.HavingExpression = new DbExpression(DbExpressionType.None, CombineWhere(havingExpressions));
            sQueryInfo.SourceQuery      = dbQuery;

            #region 更新语义

            if (updateExpression != null)
            {
                var uQueryInfo         = new DbQueryableInfo_Update <TElement>();
                var constantExpression = updateExpression.Expressions != null ? updateExpression.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    uQueryInfo.Entity = constantExpression.Value;
                }
                else
                {
                    uQueryInfo.Expression = updateExpression.Expressions[0];
                }
                uQueryInfo.SelectInfo  = sQueryInfo;
                uQueryInfo.SourceQuery = dbQuery;
                return(uQueryInfo);
            }

            #endregion

            #region  除语义

            else if (deleteExpression != null)
            {
                var dQueryInfo         = new DbQueryableInfo_Delete <TElement>();
                var constantExpression = deleteExpression.Expressions != null ? deleteExpression.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    dQueryInfo.Entity = constantExpression.Value;
                }
                dQueryInfo.SelectInfo  = sQueryInfo;
                dQueryInfo.SourceQuery = dbQuery;
                return(dQueryInfo);
            }

            #endregion

            #region 插入语义

            else if (insertExpression != null)
            {
                var nQueryInfo = new DbQueryableInfo_Insert <TElement>();
                if (insertExpression.Expressions != null)
                {
                    nQueryInfo.Entity = (insertExpression.Expressions[0] as ConstantExpression).Value;
                    if (insertExpression.Expressions.Length > 1)
                    {
                        nQueryInfo.EntityColumns = (insertExpression.Expressions[1] as ConstantExpression).Value as IList <Expression>;
                    }
                }
                nQueryInfo.SelectInfo  = sQueryInfo;
                nQueryInfo.Bulk        = dbQuery.Bulk;
                nQueryInfo.SourceQuery = dbQuery;
                dbQuery.DbQueryInfo    = nQueryInfo;
                return(nQueryInfo);
            }

            #endregion

            #region  择语义

            else if (selectExpression != null)
            {
                // 检查嵌套查询语义
                sQueryInfo = DbQueryParser.TryBuildOutQuery(sQueryInfo);
                // 查询来源
                sQueryInfo.SourceQuery = dbQuery;
            }

            #endregion

            #region 嵌套语义

            // 解析嵌套查询
            if (outerIndex != null)
            {
                var outQuery = DbQueryParser.Parse <TElement>(dbQuery, outerIndex.Value);
                var nQuery   = outQuery as DbQueryableInfo_Insert <TElement>;
                var uQuery   = outQuery as DbQueryableInfo_Update <TElement>;
                if (nQuery != null)
                {
                    if (nQuery.SelectInfo != null)
                    {
                        nQuery.SelectInfo.SubQueryInfo = sQueryInfo;
                    }
                    else
                    {
                        nQuery.SelectInfo = sQueryInfo;
                    }
                    nQuery.SourceQuery = dbQuery;
                    return(nQuery);
                }
                else if (uQuery != null)
                {
                    if (uQuery.SelectInfo != null)
                    {
                        uQuery.SelectInfo.SubQueryInfo = sQueryInfo;
                    }
                    else
                    {
                        uQuery.SelectInfo = sQueryInfo;
                    }
                    uQuery.SourceQuery = dbQuery;
                    return(uQuery);
                }
                else
                {
                    var rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        rootQuery = rootQuery.SubQueryInfo;
                    }
                    rootQuery.SubQueryInfo = sQueryInfo;
                    outQuery.SourceQuery   = dbQuery;

                    // 如果外层是统计,内层没有分页,则不需要排序
                    rootQuery = outQuery;
                    while (rootQuery.SubQueryInfo != null)
                    {
                        var myOutQuery = rootQuery as IDbQueryableInfo_Select;
                        var mySubQuery = rootQuery.SubQueryInfo as IDbQueryableInfo_Select;
                        // 没有分页的嵌套统计,不需要排序
                        if (myOutQuery.StatisExpression != null && !(mySubQuery.Take > 0 || mySubQuery.Skip > 0) && mySubQuery.OrderBys.Count > 0)
                        {
                            mySubQuery.OrderBys = new List <DbExpression>(0);
                        }
                        // 继续下一轮迭代
                        rootQuery = rootQuery.SubQueryInfo;
                    }

                    return(outQuery);
                }
            }

            #endregion

            // 查询表达式
            return(sQueryInfo);
        }
Ejemplo n.º 7
0
        // 构造由一对多关系产生的嵌套查询
        static IDbQueryableInfo_Select ParseOutQuery(IDbQueryableInfo_Select dbQuery)
        {
            // @havePaging 是否有分页信息

            if (dbQuery == null || dbQuery.Select == null)
            {
                return(dbQuery);
            }

            Expression          select   = dbQuery.Select.Expressions[0];
            List <DbExpression> includes = dbQuery.Includes;
            Type fromType = dbQuery.FromType;

            // 解析导航属性 如果有 1:n 的导航属性,那么查询的结果集的主记录将会有重复记录
            // 这时就需要使用嵌套语义,先查主记录,再关联导航记录
            Expression myExpression     = select;
            var        lambdaExpression = myExpression as LambdaExpression;

            if (lambdaExpression != null)
            {
                myExpression = lambdaExpression.Body;
            }
            var initExpression = myExpression as MemberInitExpression;
            var newExpression  = myExpression as NewExpression;

            bool hasMany = DbQueryParser.IsHasMany(includes);

            if (!hasMany)
            {
                hasMany = initExpression != null && IsHasMany(initExpression);
            }

            #region 嵌套语义

            if (hasMany)
            {
                newExpression = initExpression != null ? initExpression.NewExpression : newExpression;
                List <MemberBinding> bindings = new List <MemberBinding>();
                if (initExpression != null)
                {
                    bindings = initExpression.Bindings.ToList(x => x, x => TypeUtils.IsPrimitiveType((x.Member as System.Reflection.PropertyInfo).PropertyType));
                }

                if (newExpression != null || bindings.Count() > 0)
                {
                    // 简化内层选择器,只选择最小字段,不选择导航字段,导航字段在外层加进去
                    initExpression   = Expression.MemberInit(newExpression, bindings);
                    lambdaExpression = Expression.Lambda(initExpression, lambdaExpression.Parameters);
                    dbQuery.Select   = new DbExpression(DbExpressionType.Select, lambdaExpression);
                }
                dbQuery.IsParsedByMany = true;
                dbQuery.Includes       = new List <DbExpression>(0);

                var result_Query = new DbQueryableInfo_Select();
                result_Query.FromType = fromType;
                result_Query.Subquery = dbQuery;
                result_Query.Joins    = new List <DbExpression>(0);
                result_Query.OrderBys = new List <DbExpression>(0);
                result_Query.Includes = includes;
                result_Query.HasMany  = true;
                result_Query.Select   = new DbExpression(DbExpressionType.Select, select);

                #region 排序

                if (dbQuery.OrderBys.Count > 0)
                {
                    // 是否有分页
                    bool havePaging = (dbQuery.Take > 0 || dbQuery.Skip > 0);
                    if (!havePaging)
                    {
                        // 如果没有分页,则OrderBy需要放在外层
                        result_Query.OrderBys = dbQuery.OrderBys;
                        dbQuery.OrderBys      = new List <DbExpression>(0);
                    }
                    else
                    {
                        // 如果有分页,只有主表/用到的1:1从表放在内层,其它放在外层
                        List <DbExpression> innerOrderBy = null;
                        foreach (var dbExpression in dbQuery.OrderBys)
                        {
                            hasMany = IsHasMany(dbExpression.Expressions[0] as LambdaExpression);
                            if (!hasMany)
                            {
                                if (innerOrderBy == null)
                                {
                                    innerOrderBy = new List <DbExpression>();
                                }
                                innerOrderBy.Add(dbExpression);
                            }
                        }

                        if (innerOrderBy != null && innerOrderBy.Count > 0)
                        {
                            result_Query.OrderBys = dbQuery.OrderBys;
                            dbQuery.OrderBys      = innerOrderBy;
                        }
                    }
                }

                #endregion

                #region 分组

                if (dbQuery.GroupBy != null)
                {
                    // 查看外层是否需要重新构造选择器。如果有分组并且有聚合函数,则需要重新构造选择器。否则外层解析不了聚合函数
                    // demo => line 1280
                    bool newSelector = bindings.Any(x => ((MemberAssignment)x).Expression.NodeType == ExpressionType.Call) || newExpression.Arguments.Any(x => x.NodeType == ExpressionType.Call);
                    if (newSelector)
                    {
                        ParameterExpression newParameter  = null;
                        List <DbExpression> dbExpressions = null;
                        if (result_Query.Includes != null && result_Query.Includes.Count > 0)
                        {
                            dbExpressions = result_Query.Includes;
                        }
                        else if (result_Query.OrderBys != null && result_Query.OrderBys.Count > 0)
                        {
                            dbExpressions = result_Query.OrderBys;
                        }
                        if (dbExpressions != null && dbExpressions.Count > 0)
                        {
                            newParameter = (dbExpressions[0].Expressions[0] as LambdaExpression).Parameters[0];
                        }

                        // 1对多导航嵌套查询外层的的第一个表别名固定t0,参数名可随意
                        var parameterExpression = newParameter != null ? newParameter : Expression.Parameter(newExpression.Type, "__g");
                        bindings = bindings.ToList(x => (MemberBinding)Expression.Bind(x.Member, Expression.MakeMemberAccess(parameterExpression, x.Member)));
                        List <Expression> arguments = null;
                        if (newExpression.Members != null)
                        {
                            arguments = new List <Expression>(newExpression.Arguments.Count);
                            for (int i = 0; i < newExpression.Arguments.Count; i++)
                            {
                                var member = newExpression.Members[i];
                                var arg    = Expression.MakeMemberAccess(parameterExpression, member);
                                arguments.Add(arg);
                            }
                        }

                        newExpression       = Expression.New(newExpression.Constructor, arguments, newExpression.Members);
                        initExpression      = Expression.MemberInit(newExpression, bindings);
                        lambdaExpression    = Expression.Lambda(initExpression, parameterExpression);
                        result_Query.Select = new DbExpression(DbExpressionType.Select, lambdaExpression);
                    }
                }

                #endregion

                dbQuery = result_Query;
            }

            #endregion

            return(dbQuery);
        }
Ejemplo n.º 8
0
        // 解析查询语义
        static IDbQueryableInfo Parse(IDbQueryable source, Type elmentType, int startIndex)
        {
            // 目的:将query 转换成增/删/改/查
            // 1、from a in context.GetTable<T>() select a 此时query里面可能没有SELECT 表达式
            // 2、Take 视为一个查询的结束位,如有更多查询,应使用嵌套查询
            // 3、uion 分页查询也使嵌套语义
            // 4、uion 后面跟着 WHERE,GROUP BY,SELECT,JOIN语句时需要使用嵌套查询

            Type fromType   = null;
            bool isDistinct = false;
            bool isAny      = false;
            bool subQuery   = false;
            int? skip       = null;
            int? take       = null;
            int? outerIndex = null;
            var  conditions = new List <Expression>();              // WHERE
            var  havings    = new List <Expression>();              // HAVING
            var  joins      = new List <DbExpression>();            // JOIN
            var  orderBys   = new List <DbExpression>();            // ORDER BY
            var  includes   = new List <DbExpression>();            // ORDER BY
            var  unions     = new List <IDbQueryableInfo_Select>(); // UNION ALL

            Expression   select    = null;                          // SELECT #
            DbExpression insert    = null;                          // INSERT #
            DbExpression update    = null;                          // UPDATE #
            DbExpression delete    = null;                          // DELETE #
            DbExpression group     = null;                          // GROUP BY #
            DbExpression aggregate = null;                          // SUM&MAX  #

            for (int index = startIndex; index < source.DbExpressions.Count; index++)
            {
                DbExpression item = source.DbExpressions[index];

                // Take(n)
                if (take != null || (skip != null && item.DbExpressionType != DbExpressionType.Take) || isDistinct || subQuery)
                {
                    outerIndex = index;
                    break;
                }

                #region 解析片断

                switch (item.DbExpressionType)
                {
                case DbExpressionType.None:
                case DbExpressionType.All:
                    continue;

                case DbExpressionType.Any:
                    isAny = true;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    break;

                case DbExpressionType.AsSubquery:
                    subQuery = true;
                    continue;

                case DbExpressionType.Union:
                    var constExpression = item.Expressions[0] as ConstantExpression;
                    var uQuery          = constExpression.Value as IDbQueryable;
                    var u = DbQueryParser.Parse(uQuery, constExpression.Type.GetGenericArguments()[0], 0);
                    unions.Add((IDbQueryableInfo_Select)u);

                    // 如果下一个不是 union,就使用嵌套
                    if (index + 1 <= source.DbExpressions.Count - 1 && source.DbExpressions[index + 1].DbExpressionType != DbExpressionType.Union)
                    {
                        subQuery = true;
                    }
                    continue;

                case DbExpressionType.Include:
                    includes.Add(item);
                    continue;

                case DbExpressionType.GroupBy:
                    group = item;
                    continue;

                case DbExpressionType.GetTable:
                    fromType = (item.Expressions[0] as ConstantExpression).Value as Type;
                    continue;

                case DbExpressionType.Average:
                case DbExpressionType.Min:
                case DbExpressionType.Sum:
                case DbExpressionType.Max:
                    aggregate = item;
                    continue;

                case DbExpressionType.Count:
                    aggregate = item;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.GroupJoin:
                case DbExpressionType.GroupRightJoin:
                    select = item.Expressions[3];

                    var j = item;

                    // GetTable 的参数
                    var inner = (j.Expressions[0] as ConstantExpression).Value as IDbQueryable;
                    if (inner.DbExpressions.Count == 1 &&
                        inner.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable &&
                        inner.DbExpressions[0].Expressions.Length == 2)
                    {
                        var expressions = new Expression[item.Expressions.Length + 1];
                        Array.Copy(item.Expressions, expressions, item.Expressions.Length);
                        expressions[expressions.Length - 1] = inner.DbExpressions[0].Expressions[1];
                        j = new DbExpression(item.DbExpressionType, expressions);
                    }
                    joins.Add(j);


                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    orderBys.Add(item);
                    continue;

                case DbExpressionType.Select:
                    select = item.Expressions != null ? item.Expressions[0] : null;
                    continue;

                case DbExpressionType.SelectMany:
                    select = item.Expressions[1];
                    if (IsSelectMany(source.DbExpressions, item, startIndex))
                    {
                        joins.Add(item);
                    }
                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        conditions.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Skip:
                    skip = (int)(item.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.Take:
                    take = (int)(item.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.ThenBy:
                case DbExpressionType.ThenByDescending:
                    orderBys.Add(item);
                    continue;

                case DbExpressionType.Where:
                    var predicate = group == null ? conditions : havings;
                    if (item.Expressions != null)
                    {
                        predicate.Add(item.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Insert:
                    insert = item;
                    continue;

                case DbExpressionType.Update:
                    update = item;
                    continue;

                case DbExpressionType.Delete:
                    delete = item;
                    continue;

                default:
                    throw new NotSupportedException(string.Format("{0} is not support.", item.DbExpressionType));
                }

                #endregion
            }

            // 没有解析到INSERT/DELETE/UPDATE/SELECT表达式,并且没有相关聚合函数,则默认选择 FromEntityType 的所有字段
            bool @zero = insert == null && delete == null && update == null && select == null && aggregate == null;
            if (@zero)
            {
                select = Expression.Constant(fromType ?? elmentType);
            }

            IDbQueryableInfo_Select result_Query = new DbQueryableInfo_Select();
            result_Query.FromType    = fromType;
            result_Query.HasDistinct = isDistinct;
            result_Query.HasAny      = isAny;
            result_Query.Joins       = joins;
            result_Query.OrderBys    = orderBys;
            result_Query.GroupBy     = group;
            result_Query.Aggregate   = aggregate;
            result_Query.Unions      = unions;
            result_Query.Includes    = includes;
            result_Query.Skip        = skip != null ? skip.Value : 0;
            result_Query.Take        = take != null ? take.Value : 0;
            result_Query.Select      = new DbExpression(DbExpressionType.Select, select);
            result_Query.Where       = new DbExpression(DbExpressionType.Where, CombineCondition(conditions));
            result_Query.Having      = new DbExpression(DbExpressionType.Having, CombineCondition(havings));

            #region 更新语义

            if (update != null)
            {
                var result_Update      = new DbQueryableInfo_Update();
                var constantExpression = update.Expressions != null ? update.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    result_Update.Entity = constantExpression.Value;
                }
                else
                {
                    result_Update.Expression = update.Expressions[0];
                }
                result_Update.Query = result_Query;
                return(result_Update);
            }

            #endregion

            #region  除语义

            else if (delete != null)
            {
                var result_Delete      = new DbQueryableInfo_Delete();
                var constantExpression = delete.Expressions != null ? delete.Expressions[0] as ConstantExpression : null;
                if (constantExpression != null)
                {
                    result_Delete.Entity = constantExpression.Value;
                }
                result_Delete.Query = result_Query;
                return(result_Delete);
            }

            #endregion

            #region 插入语义

            else if (insert != null)
            {
                var result_Insert = new DbQueryableInfo_Insert();
                if (insert.Expressions != null)
                {
                    result_Insert.Entity = (insert.Expressions[0] as ConstantExpression).Value;
                    if (insert.Expressions.Length > 1)
                    {
                        result_Insert.EntityColumns = (insert.Expressions[1] as ConstantExpression).Value as IList <Expression>;
                    }
                }
                result_Insert.Query = result_Query;
                result_Insert.Bulk  = source.Bulk;
                return(result_Insert);
            }

            #endregion

            #region  择语义

            else if (select != null)
            {
                // 检查嵌套查询语义
                result_Query = DbQueryParser.ParseOutQuery(result_Query);
            }

            #endregion

            #region 嵌套语义

            // 解析嵌套查询
            if (outerIndex != null)
            {
                // todo => elementType ???
                var outQuery      = DbQueryParser.Parse(source, elmentType, outerIndex.Value);
                var result_Insert = outQuery as DbQueryableInfo_Insert;
                var result_Update = outQuery as DbQueryableInfo_Update;
                var result_Delete = outQuery as DbQueryableInfo_Delete;
                if (result_Insert != null)
                {
                    if (result_Insert.Query != null)
                    {
                        result_Insert.Query.Subquery = result_Query;
                    }
                    else
                    {
                        result_Insert.Query = result_Query;
                    }
                    return(result_Insert);
                }
                else if (result_Update != null)
                {
                    if (result_Update.Query != null)
                    {
                        result_Update.Query.Subquery = result_Query;
                    }
                    else
                    {
                        result_Update.Query = result_Query;
                    }
                    return(result_Update);
                }
                else if (result_Delete != null)
                {
                    if (result_Delete.Query != null)
                    {
                        result_Delete.Query.Subquery = result_Query;
                    }
                    else
                    {
                        result_Delete.Query = result_Query;
                    }
                    return(result_Delete);
                }
                else
                {
                    // ?? what
                    var iterator = (IDbQueryableInfo_Select)outQuery;
                    while (iterator.Subquery != null)
                    {
                        iterator = iterator.Subquery;
                    }
                    iterator.Subquery = result_Query;

                    // 如果外层是统计,内层没有分页,则不需要排序
                    iterator = (IDbQueryableInfo_Select)outQuery;
                    while (iterator.Subquery != null)
                    {
                        var myOutQuery = iterator as IDbQueryableInfo_Select;
                        var mySubQuery = iterator.Subquery as IDbQueryableInfo_Select;
                        // 没有分页的嵌套统计,不需要排序
                        if (myOutQuery.Aggregate != null && !(mySubQuery.Take > 0 || mySubQuery.Skip > 0) && mySubQuery.OrderBys.Count > 0)
                        {
                            mySubQuery.OrderBys = new List <DbExpression>(0);
                        }
                        // 继续下一轮迭代
                        iterator = iterator.Subquery;
                    }

                    return(outQuery);
                }
            }

            #endregion

            // 查询表达式
            return((IDbQueryableInfo)result_Query);
        }
Ejemplo n.º 9
0
 // 创建 SELECT 命令
 protected abstract Command ParseSelectCommand <T>(DbQueryableInfo_Select <T> sQuery, int indent, bool isOuter, ResolveToken token);
Ejemplo n.º 10
0
 // 创建 SELECT 命令
 protected abstract DbCommandDefinition ParseSelectCommand <T>(DbQueryableInfo_Select <T> sQuery, int indent = 0, bool isOuter = true, List <IDbDataParameter> parameters = null);
Ejemplo n.º 11
0
        // 构造由一对多关系产生的嵌套查询
        static DbQueryableInfo_Select <TElement> TryBuilOuter <TElement>(DbQueryableInfo_Select <TElement> sQuery)
        {
            if (sQuery == null || sQuery.Select == null)
            {
                return(sQuery);
            }

            Expression          select  = sQuery.Select.Expressions[0];
            List <DbExpression> include = sQuery.Include;
            Type type = sQuery.FromType;

            // 解析导航属性 如果有 一对多 的导航属性,那么查询的结果集的主记录将会有重复记录,这时就需要使用嵌套语义,先查主记录,再关联导航记录
            bool             checkListNavgation = false;
            Expression       expression         = select;
            LambdaExpression lambdaExpression   = expression as LambdaExpression;

            if (lambdaExpression != null)
            {
                expression = lambdaExpression.Body;
            }
            MemberInitExpression initExpression = expression as MemberInitExpression;
            NewExpression        newExpression  = expression as NewExpression;

            foreach (DbExpression d in include)
            {
                Expression exp = d.Expressions[0];
                if (exp.NodeType == ExpressionType.Lambda)
                {
                    exp = (exp as LambdaExpression).Body;
                }
                else if (exp.NodeType == ExpressionType.Call)
                {
                    exp = (exp as MethodCallExpression).Object;
                }

                // Include 如果包含List<>泛型导航,则可以判定整个查询包含一对多的导航
                //if (exp.Type.IsGenericType && exp.Type.GetGenericTypeDefinition() == typeof(List<>)) checkListNavgation = true;
                if (TypeUtils.IsCollectionType(exp.Type))
                {
                    checkListNavgation = true;
                }
                if (checkListNavgation)
                {
                    break;
                }
            }
            if (!checkListNavgation)
            {
                checkListNavgation = initExpression != null && CheckListNavigation <TElement>(initExpression);
            }

            if (checkListNavgation)
            {
                newExpression = initExpression != null ? initExpression.NewExpression : newExpression;
                List <MemberBinding> bindings = new List <MemberBinding>();
                if (initExpression != null)
                {
                    bindings = initExpression.Bindings.ToList(x => x, x => TypeUtils.IsPrimitiveType((x.Member as System.Reflection.PropertyInfo).PropertyType));
                }

                if (newExpression != null || bindings.Count() > 0)
                {
                    // 简化内层选择器,只选择最小字段,不选择导航字段,导航字段在外层加进去
                    initExpression   = Expression.MemberInit(newExpression, bindings);
                    lambdaExpression = Expression.Lambda(initExpression, lambdaExpression.Parameters);
                    sQuery.Select    = new DbExpression(DbExpressionType.Select, lambdaExpression);
                }
                sQuery.GenByListNavigation = true;
                sQuery.Include             = new List <DbExpression>();

                var outQuery = new DbQueryableInfo_Select <TElement>();
                outQuery.FromType           = type;
                outQuery.SubQueryInfo       = sQuery;
                outQuery.Join               = new List <DbExpression>();
                outQuery.OrderBy            = new List <DbExpression>();
                outQuery.Include            = include;
                outQuery.HaveListNavigation = true;
                outQuery.Select             = new DbExpression(DbExpressionType.Select, select);
                if (sQuery.GroupBy != null)
                {
                    // 查看外层是否需要重新构造选择器。如果有分组并且有聚合函数,则需要重新构造选择器。否则外层解析不了聚合函数
                    // demo=> line 640
                    bool newSelector = bindings.Any(x => ((MemberAssignment)x).Expression.NodeType == ExpressionType.Call) ||
                                       newExpression.Arguments.Any(x => x.NodeType == ExpressionType.Call);
                    if (newSelector)
                    {
                        // 1对多导航嵌套查询外层的的第一个表别名固定t0,参数名可随意
                        ParameterExpression p = Expression.Parameter(newExpression.Type, "__g");
                        bindings = bindings.ToList(x => (MemberBinding)Expression.Bind(x.Member, Expression.MakeMemberAccess(p, x.Member)));
                        List <Expression> arguments = null;
                        if (newExpression.Members != null)
                        {
                            arguments = new List <Expression>(newExpression.Arguments.Count);
                            for (int i = 0; i < newExpression.Arguments.Count; i++)
                            {
                                var member = newExpression.Members[i];
                                var arg    = Expression.MakeMemberAccess(p, member);
                                arguments.Add(arg);
                            }
                        }

                        newExpression    = Expression.New(newExpression.Constructor, arguments, newExpression.Members);
                        initExpression   = Expression.MemberInit(newExpression, bindings);
                        lambdaExpression = Expression.Lambda(initExpression, lambdaExpression.Parameters);
                        outQuery.Select  = new DbExpression(DbExpressionType.Select, lambdaExpression);
                    }
                }

                sQuery = outQuery;
            }
            else if (sQuery.Union.Count > 0 && (sQuery.Take > 0 || sQuery.Skip > 0))
            {
                var outQuery = new DbQueryableInfo_Select <TElement>();
                outQuery.FromType     = type;
                outQuery.Select       = new DbExpression(DbExpressionType.Select, select);
                outQuery.SubQueryInfo = sQuery;
                outQuery.Skip         = sQuery.Skip;
                outQuery.Take         = sQuery.Take;
                outQuery.Join         = new List <DbExpression>();
                outQuery.OrderBy      = new List <DbExpression>();
                outQuery.OrderBy.AddRange(sQuery.OrderBy);

                sQuery.OrderBy = new List <DbExpression>();
                sQuery.Skip    = 0;
                sQuery.Take    = 0;

                sQuery = outQuery;
            }

            return(sQuery);
        }
Ejemplo n.º 12
0
        // 解析查询语义
        static IDbQueryableInfo <TElement> Parse <TElement>(IDbQueryable <TElement> dbQuery, int startIndex)
        {
            // 目的:将query 转换成增/删/改/查
            // 1、from a in context.GetTable<T>() select a 此时query里面可能没有SELECT 表达式
            // 2、Take 视为一个查询的结束位,如有更多查询,应使用嵌套查询
            // 3、Uion 分页查询也使嵌套语义

            Type type       = null;
            bool isDistinct = false;
            bool isAny      = false;
            bool isSubQuery = false;
            int? skip       = null;
            int? take       = null;
            int? outerIndex = null;

            List <Expression> where = new List <Expression>();                // WHERE
            List <Expression>   having  = new List <Expression>();            // HAVING
            List <DbExpression> join    = new List <DbExpression>();          // JOIN
            List <DbExpression> orderBy = new List <DbExpression>();          // ORDER BY
            List <DbExpression> include = new List <DbExpression>();          // ORDER BY
            List <IDbQueryableInfo <TElement> > union = new List <IDbQueryableInfo <TElement> >();

            Expression   select  = null;    // SELECT #
            DbExpression insert  = null;    // INSERT #
            DbExpression update  = null;    // UPDATE #
            DbExpression delete  = null;    // DELETE #
            DbExpression groupBy = null;    // GROUP BY #
            DbExpression statis  = null;    // SUM/MAX  #

            for (int index = startIndex; index < dbQuery.DbExpressions.Count; ++index)
            {
                DbExpression curExpr = dbQuery.DbExpressions[index];

                // Take(n)
                if (take != null || (skip != null && curExpr.DbExpressionType != DbExpressionType.Take) || isDistinct || isSubQuery)
                {
                    outerIndex = index;
                    break;
                }

                #region 分析语义

                switch (curExpr.DbExpressionType)
                {
                case DbExpressionType.None:
                case DbExpressionType.All:
                    continue;

                case DbExpressionType.Any:
                    isAny = true;
                    if (curExpr.Expressions != null)
                    {
                        where.Add(curExpr.Expressions[0]);
                    }
                    break;

                case DbExpressionType.AsSubQuery:
                    isSubQuery = true;
                    //if (curExp.Expressions != null) where.Add(curExp.Expressions[0]);
                    break;

                case DbExpressionType.Union:
                    var uQuery = (curExpr.Expressions[0] as ConstantExpression).Value as IDbQueryable <TElement>;
                    var u      = DbQueryParser.Parse(uQuery);
                    union.Add(u);
                    continue;

                case DbExpressionType.Include:
                    include.Add(curExpr);
                    continue;

                case DbExpressionType.GroupBy:
                    groupBy = curExpr;
                    continue;

                case DbExpressionType.GetTable:
                    type = (curExpr.Expressions[0] as ConstantExpression).Value as Type;
                    continue;

                case DbExpressionType.Average:
                case DbExpressionType.Min:
                case DbExpressionType.Sum:
                case DbExpressionType.Max:
                    statis = curExpr;
                    continue;

                case DbExpressionType.Count:
                    statis = curExpr;
                    if (curExpr.Expressions != null)
                    {
                        where.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        where.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.GroupJoin:
                case DbExpressionType.GroupRightJoin:
                    select = curExpr.Expressions[3];
                    join.Add(curExpr);
                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    orderBy.Add(curExpr);
                    continue;

                case DbExpressionType.Select:
                    select = curExpr.Expressions != null ? curExpr.Expressions[0] : null;
                    continue;

                case DbExpressionType.SelectMany:
                    select = curExpr.Expressions[1];
                    if (CheckSelectMany(dbQuery.DbExpressions, curExpr, startIndex))
                    {
                        join.Add(curExpr);
                    }

                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (curExpr.Expressions != null)
                    {
                        where.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Skip:
                    skip = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.Take:
                    take = (int)(curExpr.Expressions[0] as ConstantExpression).Value;
                    continue;

                case DbExpressionType.ThenBy:
                case DbExpressionType.ThenByDescending:
                    orderBy.Add(curExpr);
                    continue;

                case DbExpressionType.Where:
                    var predicate = groupBy == null ? where : having;
                    if (curExpr.Expressions != null)
                    {
                        predicate.Add(curExpr.Expressions[0]);
                    }
                    continue;

                case DbExpressionType.Insert:
                    insert = curExpr;
                    continue;

                case DbExpressionType.Update:
                    update = curExpr;
                    continue;

                case DbExpressionType.Delete:
                    delete = curExpr;
                    continue;

                default:
                    throw new NotSupportedException(string.Format("{0} is not support.", curExpr.DbExpressionType));
                }

                #endregion
            }

            // 没有解析到INSERT/DELETE/UPDATE/SELECT表达式,并且没有相关统计函数,则默认选择FromType的所有字段
            bool useFullColumns = insert == null && delete == null && update == null && select == null && statis == null;
            if (useFullColumns)
            {
                select = Expression.Constant(type ?? typeof(TElement));
            }

            var sQuery = new DbQueryableInfo_Select <TElement>();
            sQuery.FromType     = type;
            sQuery.HaveDistinct = isDistinct;
            sQuery.HaveAny      = isAny;
            sQuery.Join         = join;
            sQuery.OrderBy      = orderBy;
            sQuery.GroupBy      = groupBy;
            sQuery.Statis       = statis;
            sQuery.Union        = union;
            sQuery.Include      = include;
            sQuery.Skip         = skip != null ? skip.Value : 0;
            sQuery.Take         = take != null ? take.Value : 0;
            sQuery.Select       = new DbExpression(DbExpressionType.Select, select);
            sQuery.Where        = new DbExpression(DbExpressionType.Where, DbQueryParser.CombineWhere(where));
            sQuery.Having       = new DbExpression(DbExpressionType.None, DbQueryParser.CombineWhere(having));
            sQuery.SourceQuery  = dbQuery;

            // 更新
            if (update != null)
            {
                var uQuery = new DbQueryableInfo_Update <TElement>();
                ConstantExpression expression2 = update.Expressions != null ? update.Expressions[0] as ConstantExpression : null;
                if (expression2 != null)
                {
                    uQuery.Entity = expression2.Value;
                }
                else
                {
                    uQuery.Expression = update.Expressions[0];
                }
                uQuery.SelectInfo  = sQuery;
                uQuery.SourceQuery = dbQuery;
                return(uQuery);
            }

            // 删除
            if (delete != null)
            {
                var dQuery = new DbQueryableInfo_Delete <TElement>();
                ConstantExpression expression2 = delete.Expressions != null ? delete.Expressions[0] as ConstantExpression : null;
                if (expression2 != null)
                {
                    dQuery.Entity = expression2.Value;
                }
                dQuery.SelectInfo  = sQuery;
                dQuery.SourceQuery = dbQuery;
                return(dQuery);
            }

            // 新增
            if (insert != null)
            {
                var nQuery = new DbQueryableInfo_Insert <TElement>();
                if (insert.Expressions != null)
                {
                    nQuery.Entity = (insert.Expressions[0] as ConstantExpression).Value;
                    if (insert.Expressions.Length > 1)
                    {
                        nQuery.EntityColumns = (insert.Expressions[1] as ConstantExpression).Value as IList <Expression>;
                    }
                }
                nQuery.SelectInfo   = sQuery;
                nQuery.Bulk         = dbQuery.Bulk;
                nQuery.SourceQuery  = dbQuery;
                dbQuery.DbQueryInfo = nQuery;
                return(nQuery);
            }

            // 如果有一对多的导航关系,则产生嵌套语义的查询
            if (select != null)
            {
                // 如果有uion但是没分页,应去掉orderby子句
                if (sQuery.Union.Count > 0 && !(sQuery.Take > 0 || sQuery.Skip > 0))
                {
                    sQuery.OrderBy = new List <DbExpression>();
                }
                // 检查嵌套查询语义
                sQuery             = DbQueryParser.TryBuilOuter(sQuery);
                sQuery.SourceQuery = dbQuery;
            }

            // 解析嵌套查询
            if (outerIndex != null)
            {
                var outQuery = DbQueryParser.Parse <TElement>(dbQuery, outerIndex.Value);
                var nQuery   = outQuery as DbQueryableInfo_Insert <TElement>;
                var uQuery   = outQuery as DbQueryableInfo_Update <TElement>;
                if (nQuery != null)
                {
                    if (nQuery.SelectInfo != null)
                    {
                        nQuery.SelectInfo.SubQueryInfo = sQuery;
                    }
                    else
                    {
                        nQuery.SelectInfo = sQuery;
                    }
                    nQuery.SourceQuery = dbQuery;
                    return(nQuery);
                }
                else if (uQuery != null)
                {
                    if (uQuery.SelectInfo != null)
                    {
                        uQuery.SelectInfo.SubQueryInfo = sQuery;
                    }
                    else
                    {
                        uQuery.SelectInfo = sQuery;
                    }
                    uQuery.SourceQuery = dbQuery;
                    return(uQuery);
                }
                else
                {
                    outQuery.SubQueryInfo = sQuery;
                    outQuery.SourceQuery  = dbQuery;
                    return(outQuery);
                }
            }

            // 查询表达式
            return(sQuery);
        }