示例#1
0
 /// <summary>
 /// 添加额外查询
 /// <para>
 /// 例:SELECT FieldName FROM TableName WHERE Condition={0} AND Condition1={1}
 /// </para>
 /// </summary>
 /// <param name="sql">SQL 命令</param>
 /// <param name="args">参数列表</param>
 public void AddQuery(string sql, params object[] args)
 {
     if (!string.IsNullOrEmpty(sql))
     {
         var query = new DbRawSql(this, sql, args);
         _dbQueryables.Add(query);
     }
 }
        /// <summary>
        /// 访问表达式节点
        /// </summary>
        /// <param name="wheres">筛选表达式</param>
        public override Expression Visit(List <DbExpression> wheres)
        {
            if (wheres != null && wheres.Count > 0)
            {
                _builder.AppendNewLine();
                _builder.Append("WHERE ");

                for (int index = 0; index < wheres.Count; index++)
                {
                    DbExpression d    = wheres[index];
                    var          node = d.Expressions[0];
                    if (node.NodeType == ExpressionType.Lambda)
                    {
                        node = ((LambdaExpression)node).Body;
                    }
                    node = BooleanUnaryToBinary(node);

                    if (!(node is ConstantExpression))
                    {
                        base.Visit(node);
                    }
                    else
                    {
                        // 字符符动态SQL,解析参数
                        DbRawSql rawSql = (node as ConstantExpression).Value as DbRawSql;
                        object[] args   = null;
                        if (rawSql.Parameters != null)
                        {
                            args = rawSql.Parameters.Select(x => _constor.GetSqlValue(x, _context)).ToArray();
                        }
                        string sql = rawSql.CommandText;

                        if (args != null && args.Length > 0)
                        {
                            sql = string.Format(sql, args);
                        }
                        _builder.Append(sql);
                    }

                    if (index < wheres.Count - 1)
                    {
                        _builder.Append(" AND ");
                    }
                }
            }

            return(null);
        }
        // 解析查询语义
        private static IDbQueryTree 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;
            DbRawSql                 rawSql     = null;
            bool                     isDistinct = false;
            bool                     isAny      = false;
            bool                     isSubquery = false;
            int?                     skip       = null;
            int?                     take       = null;
            int?                     outerIndex = null;
            List <DbExpression>      wheres     = null; // WHERE
            List <DbExpression>      havings    = null; // HAVING
            List <DbExpression>      joins      = null; // JOIN
            List <DbExpression>      orderBys   = null; // ORDER BY
            List <DbExpression>      includes   = null; // ORDER BY
            List <DbQuerySelectTree> unions     = null; // UNION ALL

            Expression   pickExpression = null;
            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 || isSubquery)
                {
                    outerIndex = index;
                    break;
                }

                #region 解析片断

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

                case DbExpressionType.Any:
                    isAny = true;
                    if (item.Expressions != null)
                    {
                        if (wheres == null)
                        {
                            wheres = new List <DbExpression>();
                        }
                        wheres.Add(item);
                    }
                    break;

                case DbExpressionType.AsSubquery:
                    isSubquery = true;
                    continue;

                case DbExpressionType.Union:
                    var constExpression = item.Expressions[0] as ConstantExpression;
                    var uQuery          = constExpression.Value as IDbQueryable;
                    var u = DbQueryableParser.Parse(uQuery, constExpression.Type.GetGenericArguments()[0], 0);
                    if (unions == null)
                    {
                        unions = new List <DbQuerySelectTree>();
                    }
                    unions.Add((DbQuerySelectTree)u);

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

                case DbExpressionType.Include:
                    if (includes == null)
                    {
                        includes = new List <DbExpression>();
                    }
                    includes.Add(item);
                    continue;

                case DbExpressionType.GroupBy:
                    group = item;
                    continue;

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

                    if (fromType == null)
                    {
                        string text = (item.Expressions[0] as ConstantExpression).Value as string;
                        if (text != null)
                        {
                            rawSql = new DbRawSql(null, text, (object[])(item.Expressions[1] as ConstantExpression).Value);
                        }
                    }

                    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)
                    {
                        if (wheres == null)
                        {
                            wheres = new List <DbExpression>();
                        }
                        wheres.Add(item);
                    }
                    continue;

                case DbExpressionType.Distinct:
                    isDistinct = true;
                    continue;

                case DbExpressionType.First:
                case DbExpressionType.FirstOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        if (wheres == null)
                        {
                            wheres = new List <DbExpression>();
                        }
                        wheres.Add(item);
                    }
                    continue;

                case DbExpressionType.Join:
                case DbExpressionType.LeftOuterJoin:
                case DbExpressionType.RightOuterJoin:
                    pickExpression = 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)
                    {
                        // 区别 GetTable 有三个重载,这里处理指定外键路径的重载
                        if (inner.DbExpressions[0].Expressions.Length == 2 && (inner.DbExpressions[0].Expressions[0] as ConstantExpression).Value is Type)
                        {
                            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);
                        }
                    }

                    if (joins == null)
                    {
                        joins = new List <DbExpression>();
                    }
                    joins.Add(j);

                    continue;

                case DbExpressionType.OrderBy:
                case DbExpressionType.OrderByDescending:
                    if (orderBys == null)
                    {
                        orderBys = new List <DbExpression>();
                    }
                    orderBys.Add(item);
                    continue;

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

                case DbExpressionType.SelectMany:
                    pickExpression = item.Expressions[1];
                    if (IsCrossJoinExression(source.DbExpressions, item, startIndex))
                    {
                        if (joins == null)
                        {
                            joins = new List <DbExpression>();
                        }
                        joins.Add(item);
                    }
                    continue;

                case DbExpressionType.Single:
                case DbExpressionType.SingleOrDefault:
                    take = 1;
                    if (item.Expressions != null)
                    {
                        if (wheres == null)
                        {
                            wheres = new List <DbExpression>();
                        }
                        wheres.Add(item);
                    }
                    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:
                    if (orderBys == null)
                    {
                        orderBys = new List <DbExpression>();
                    }
                    orderBys.Add(item);
                    continue;

                case DbExpressionType.Where:
                    if (item.Expressions != null)
                    {
                        if (group == null)
                        {
                            if (wheres == null)
                            {
                                wheres = new List <DbExpression>();
                            }
                            wheres.Add(item);
                        }
                        else
                        {
                            if (havings == null)
                            {
                                havings = new List <DbExpression>();
                            }
                            havings.Add(item);
                        }
                    }
                    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 的所有字段
            if (insert == null && delete == null && update == null && pickExpression == null && aggregate == null)
            {
                pickExpression = Expression.Constant(fromType ?? elmentType);
            }
            DbExpression select = new DbExpression(DbExpressionType.Select, pickExpression);
            if (fromType == null)
            {
                fromType = elmentType;
            }

            var result_Query = new DbQuerySelectTree();
            result_Query.From        = fromType;
            result_Query.FromSql     = rawSql;
            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      = select;
            result_Query.Wheres      = wheres;
            result_Query.Havings     = havings;

            #region 更新语义

            if (update != null)
            {
                var result_Update      = new DbQueryUpdateTree();
                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.Select = result_Query;
                return(result_Update);
            }

            #endregion

            #region  除语义

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

            #endregion

            #region 插入语义

            else if (insert != null)
            {
                var result_Insert = new DbQueryInsertTree();
                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.Select = result_Query;
                result_Insert.Bulk   = ((DbQueryable)source).Bulk;
                return(result_Insert);
            }

            #endregion

            #region  择语义

            else if (pickExpression != null)
            {
                // 检查嵌套查询语义
                result_Query = DbQueryableParser.TryParseOutQuery(result_Query);
            }

            #endregion

            #region 嵌套语义

            // 解析嵌套查询
            if (outerIndex != null)
            {
                // todo => elementType ???
                var outQueryTree  = DbQueryableParser.Parse(source, elmentType, outerIndex.Value);
                var result_Insert = outQueryTree as DbQueryInsertTree;
                var result_Update = outQueryTree as DbQueryUpdateTree;
                var result_Delete = outQueryTree as DbQueryDeleteTree;
                if (result_Insert != null)
                {
                    if (result_Insert.Select != null)
                    {
                        result_Insert.Select.Subquery = result_Query;
                    }
                    else
                    {
                        result_Insert.Select = result_Query;
                    }
                    return(result_Insert);
                }
                else if (result_Update != null)
                {
                    if (result_Update.Select != null)
                    {
                        result_Update.Select.Subquery = result_Query;
                    }
                    else
                    {
                        result_Update.Select = result_Query;
                    }
                    return(result_Update);
                }
                else if (result_Delete != null)
                {
                    if (result_Delete.Select != null)
                    {
                        result_Delete.Select.Subquery = result_Query;
                    }
                    else
                    {
                        result_Delete.Select = result_Query;
                    }
                    return(result_Delete);
                }
                else
                {
                    // 指定子查询
                    var iterator = (DbQuerySelectTree)outQueryTree;
                    while (iterator.Subquery != null)
                    {
                        iterator = iterator.Subquery;
                    }
                    iterator.Subquery = result_Query;

                    //// ?? AsSubquery(a=>a),那么它所有的外层字段都要基于里层的字段
                    //if (isSubquery && startIndex == 0)
                    //    LimitSelector((DbQuerySelectTree)outQueryTree);

                    // 如果外层是统计,内层没有分页,则不需要排序
                    iterator = (DbQuerySelectTree)outQueryTree;
                    while (iterator.Subquery != null)
                    {
                        // 没有分页的嵌套统计,不需要排序
                        if (iterator.Aggregate != null && !(iterator.Subquery.Take > 0 || iterator.Subquery.Skip > 0) && iterator.Subquery.OrderBys != null && iterator.Subquery.OrderBys.Count > 0)
                        {
                            iterator.Subquery.OrderBys = new List <DbExpression>(0);
                        }

                        // 继续下一轮迭代
                        iterator = iterator.Subquery;
                    }

                    return(outQueryTree);
                }
            }

            #endregion

            // 查询表达式
            return(result_Query);
        }
示例#4
0
        /// <summary>
        /// 解析 SQL 命令
        /// <para>
        /// 返回的已经解析语义中执行批次用 null 分开
        /// </para>
        /// </summary>
        /// <param name="dbQueryables">查询语句</param>
        /// <returns></returns>
        public virtual List <DbRawCommand> Translate(List <object> dbQueryables)
        {
            ITranslateContext context = null;
            var sqlList = new List <DbRawCommand>();

            foreach (var obj in dbQueryables)
            {
                if (obj == null)
                {
                    continue;
                }

                if (obj is IDbQueryable)
                {
                    DbQueryable dbQuery = (DbQueryable)obj;
                    dbQuery.Parameterized = true;
                    if (context == null)
                    {
                        context = this.CreateTranslateContext(dbQuery.DbContext);
                    }
                    if (context.Parameters == null)
                    {
                        context.Parameters = new List <IDbDataParameter>(8);
                    }

                    var cmd = dbQuery.Translate(0, true, context);
                    sqlList.Add(cmd);
                    if (cmd.Parameters != null && cmd.Parameters.Count > 1000)
                    {
                        // 1000个参数,就要重新分批
                        sqlList.Add(null);
                        context            = this.CreateTranslateContext(dbQuery.DbContext);
                        context.Parameters = new List <IDbDataParameter>(8);
                    }
                }
                else if (obj is DbRawSql)
                {
                    DbRawSql rawSql = (DbRawSql)obj;
                    if (context == null)
                    {
                        context = this.CreateTranslateContext(rawSql.DbContext);
                    }
                    if (context.Parameters == null)
                    {
                        context.Parameters = new List <IDbDataParameter>(8);
                    }

                    // 解析参数
                    object[] args = null;
                    if (rawSql.Parameters != null)
                    {
                        args = rawSql.Parameters.Select(x => this.Constor.GetSqlValue(x, context)).ToArray();
                    }
                    string sql = rawSql.CommandText;
                    if (args != null && args.Length > 0)
                    {
                        sql = string.Format(sql, args);
                    }

                    var cmd = new DbRawCommand(sql, context.Parameters, CommandType.Text);
                    sqlList.Add(cmd);
                    if (cmd.Parameters != null && cmd.Parameters.Count > 1000)
                    {
                        // 1000个参数,就要重新分批
                        sqlList.Add(null);
                        context            = this.CreateTranslateContext(rawSql.DbContext);
                        context.Parameters = new List <IDbDataParameter>(8);
                    }
                }
                else if (obj is string)
                {
                    string sql = obj.ToString();
                    sqlList.Add(new DbRawCommand(sql));
                }
                else
                {
                    // 解析批量插入操作
                    List <IDbQueryable> bulkList = obj as List <IDbQueryable>;
                    if (bulkList != null && bulkList.Count > 0)
                    {
                        this.TranslateBulk(sqlList, bulkList);
                    }
                }
            }

            return(sqlList);
        }