/// <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); }
/// <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); }