// Cross Join private void AppendCrossJoin(ISqlBuilder jf, DbExpression exp, TableAliasCache aliases) { if (!_appendedKeyword) { jf.AppendNewLine(); jf.Append(_keywordName); _appendedKeyword = true; } else { jf.Append(','); jf.AppendNewLine(); jf.Append(" "); } LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression; Type type = lambdaExp.Parameters[1].Type; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); jf.Append(' '); jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); string alias = aliases.GetTableAlias(lambdaExp.Parameters[1]); jf.Append(' '); jf.Append(alias); }
/// <summary> /// 初始化 <see cref="JoinExpressionVisitor"/> 类的新实例 /// </summary> public JoinExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, List <DbExpression> qJoin) : base(provider, aliases, null, false) { _qJoin = qJoin; _aliases = aliases; _provider = provider; }
/// <summary> /// 追加列名 /// </summary> /// <param name="aliases">表别名</param> /// <param name="expression">列名表达式</param> /// <returns>返回解析到的表别名</returns> public string AppendMember(TableAliasCache aliases, Expression expression) { Expression exp = expression; LambdaExpression lambdaExpression = exp as LambdaExpression; if (lambdaExpression != null) { exp = lambdaExpression.Body; } if (expression.CanEvaluate()) { ConstantExpression c = expression.Evaluate(); string value = this.GetSqlValue(c.Value); _innerBuilder.Append(value); return(value); } else { MemberExpression m = expression as MemberExpression; string alias = aliases == null ? null : aliases.GetTableAlias(m); this.AppendMember(alias, m.Member.Name); return(alias); } }
/// <summary> /// 实例化 <see cref="Builder" /> 的新实例 /// </summary> public OracleDeleteDbCommandDefinition(IDbQueryProvider provider, TableAliasCache aliases, List <IDbDataParameter> parameters) : base(provider, aliases, parameters) { _provider = provider; _aliases = aliases; _onPhrase = _provider.CreateSqlBuilder(parameters); }
/// <summary> /// 初始化 <see cref="OracleJoinExpressionVisitor"/> 类的新实例 /// </summary> public OracleJoinExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, List <DbExpression> qJoin, DbExpression qWhere) : base(provider, aliases, null, false) { _provider = provider; _qJoin = qJoin; _aliases = aliases; _where = qWhere; }
/// <summary> /// 初始化 <see cref="ExpressionVisitorBase"/> 类的新实例 /// </summary> public ExpressionVisitorBase(IDbQueryProvider provider, TableAliasCache aliases, Expression exp, bool useNominate = true) { _provider = provider; _aliases = aliases; _expression = exp; _visitedMember = new VisitedMemberList(); _navMembers = new Dictionary <string, MemberExpression>(); }
// 获取 CROSS JOIN 子句关联表的的别名 private void PrepareCrossJoinAlias(DbExpression exp, TableAliasCache aliases) { LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression; for (int index = 0; index < lambdaExp.Parameters.Count; ++index) { aliases.GetTableAlias(lambdaExp.Parameters[index]); } }
/// <summary> /// 初始化 <see cref="StatisExpressionVisitor"/> 类的新实例 /// </summary> public StatisExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, DbExpression statis, DbExpression groupBy = null, string alias = null) : base(provider, aliases, statis.Expressions != null ? statis.Expressions[0] : null, false) { _provider = provider; _aliases = aliases; _statis = statis; _groupBy = groupBy; _alias = alias; }
/// <summary> /// 初始化 <see cref="OrderByExpressionVisitor"/> 类的新实例 /// </summary> public OrderByExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, List <DbExpression> qOrder, DbExpression groupBy = null, string alias = null) : base(provider, aliases, null, false) { _qOrder = qOrder; _aliases = aliases; _groupBy = groupBy; _alias = alias; _provider = provider; }
/// <summary> /// 实例化 <see cref="SelectDbCommandDefinition"/> 类的新实例 /// </summary> /// <param name="provider">数据查询提供者</param> /// <param name="aliases">别名</param> /// <param name="parameters">已存在的参数列表</param> public SelectDbCommandDefinition(IDbQueryProvider provider, TableAliasCache aliases, List <IDbDataParameter> parameters) : base(string.Empty, null, System.Data.CommandType.Text) { _provider = provider; _aliases = aliases; _navMembers = new Dictionary <string, MemberExpression>(); _joinFragment = provider.CreateSqlBuilder(parameters); _whereFragment = provider.CreateSqlBuilder(parameters); }
/// <summary> /// 根据指定表达式取表别名 /// </summary> /// <param name="exp">表达式</param> /// <remarks> /// t=>t.Id /// t.Id /// </remarks> public string GetTableAlias(Expression exp) { // p=>p.p // p=>p.Id // p=>p.t.Id // p.Id // p.t.Id // p.t // <>h__TransparentIdentifier0.p.Id XFrameworkException.Check.NotNull(exp, "exp"); string key = TableAliasCache.GetTableAliasKey(exp); return(this.GetTableAlias(key)); }
private static string GetTableAliasKey(Expression exp) { if (exp == null) { return(null); } Expression expression = exp.ReduceUnary(); //c if (exp.CanEvaluate()) { return(null); } // p ParameterExpression paramExp = expression as ParameterExpression; if (paramExp != null) { return(paramExp.Name); } // a=>a.Id LambdaExpression lambdaExp = expression as LambdaExpression; if (lambdaExp != null) { expression = lambdaExp.Body.ReduceUnary(); } // a.Id // t.a // t.t.a // t.a.Id MemberExpression memExp = expression as MemberExpression; if (memExp == null) { return(TableAliasCache.GetTableAliasKey(expression)); } if (memExp.Acceptable()) { return(TableAliasCache.GetTableAliasKey(memExp.Expression)); } return(memExp.Member.Name); }
// Cross Join private void AppendCrossJoin(ISqlBuilder builder, DbExpression exp, TableAliasCache aliases) { LambdaExpression lambdaExp = exp.Expressions[1] as LambdaExpression; Type type = lambdaExp.Parameters[1].Type; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); builder.Append(' '); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); string alias = aliases.GetTableAlias(lambdaExp.Parameters[1]); builder.Append(' '); builder.Append(alias); builder.Append(' '); }
/// <summary> /// 初始化 <see cref="JoinExpressionVisitor"/> 类的新实例 /// </summary> public NpgJoinExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, List <DbExpression> qJoin, NpgCommandType operationType) : base(provider, aliases, null, false) { _qJoin = qJoin; _aliases = aliases; _operationType = operationType; if (_operationType == NpgCommandType.DELETE) { _keywordName = "USING"; } else if (_operationType == NpgCommandType.UPDATE) { _keywordName = "FROM"; } }
// 获取 LEFT JOIN / INNER JOIN 子句关联表的的别名 private void PrepareLfInJoinAlias(DbExpression exp, TableAliasCache aliases) { Type type = exp.Expressions[0].Type.GetGenericArguments()[0]; string name = TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName; // on a.Name equals b.Name 或 on new{ Name = a.Name,Id=a.Id } equals new { Name = b.Name,Id=b.Id } LambdaExpression left = exp.Expressions[1] as LambdaExpression; LambdaExpression right = exp.Expressions[2] as LambdaExpression; if (left.Body.NodeType == ExpressionType.New) { NewExpression body1 = left.Body as NewExpression; NewExpression body2 = right.Body as NewExpression; for (int index = 0; index < body1.Arguments.Count; ++index) { aliases.GetTableAlias(body1.Arguments[index]); } for (int index = 0; index < body2.Arguments.Count; ++index) { string alias = aliases.GetTableAlias(body2.Arguments[index]); // 记录显示指定的LEFT JOIN 表别名 aliases.AddOrUpdateJoinTableAlias(name, alias); } } else if (left.Body.NodeType == ExpressionType.MemberInit) { MemberInitExpression body1 = left.Body as MemberInitExpression; MemberInitExpression body2 = right.Body as MemberInitExpression; for (int index = 0; index < body1.Bindings.Count; ++index) { aliases.GetTableAlias((body1.Bindings[index] as MemberAssignment).Expression); } for (int index = 0; index < body2.Bindings.Count; ++index) { string alias = aliases.GetTableAlias((body2.Bindings[index] as MemberAssignment).Expression); // 记录显示指定的LEFT JOIN 表别名 aliases.AddOrUpdateJoinTableAlias(name, alias); } } else { aliases.GetTableAlias(exp.Expressions[1]); string alias = aliases.GetTableAlias(exp.Expressions[2]); // 记录显示指定的LEFT JOIN 表别名 aliases.AddOrUpdateJoinTableAlias(name, alias); } }
/// <summary> /// 初始化 <see cref="ColumnExpressionVisitor"/> 类的新实例 /// </summary> public ColumnExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, IDbQueryableInfo_Select qQuery) : base(provider, aliases, qQuery.Select.Expressions != null ? qQuery.Select.Expressions[0] : null) { _provider = provider; _aliases = aliases; _qQuery = qQuery; _groupBy = qQuery.GroupBy; _include = qQuery.Include; if (_columns == null) { _columns = new Dictionary <string, Column>(); } _navigations = new NavigationCollection(); _navChainHopper = new List <string>(10); _visitedNavigations = new Dictionary <string, string>(8); }
/// <summary> /// 实例化 <see cref="Builder" /> 的新实例 /// </summary> public NpgDeleteDbCommandDefinition(IDbQueryProvider provider, TableAliasCache aliases, NpgCommandType operationType, List <IDbDataParameter> parameters) : base(provider, aliases, parameters) { _provider = provider; _aliases = aliases; _onPhrase = _provider.CreateSqlBuilder(parameters); _operationType = operationType; if (_operationType == NpgCommandType.DELETE) { _keywordName = "USING"; } else if (_operationType == NpgCommandType.UPDATE) { _keywordName = "FROM"; } }
// 获取 JOIN 子句关联表的的别名 protected TableAliasCache PrepareAlias <T>(DbQueryableInfo_Select <T> query) { TableAliasCache aliases = new TableAliasCache((query.Join != null ? query.Join.Count : 0) + 1); foreach (DbExpression exp in query.Join) { // [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); }
/// <summary> /// 初始化 <see cref="NpgWhereExpressionVisitor"/> 类的新实例 /// </summary> public NpgWhereExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, DbExpression exp) : base(provider, aliases, exp) { _expression = exp != null && exp.Expressions != null ? exp.Expressions[0] : null; }
// 添加导航属性关联 protected override void AppendNavigation() { if (this.NavMembers == null || this.NavMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HaveListNavigation) { _aliases = new TableAliasCache(_aliases.ObviousAlias); } //开始产生 USING 子句 ISqlBuilder jf = this.JoinFragment; int index = -1; // 未生成USING子句 if (_aliases.ObviousAlias <= 1) { jf.AppendNewLine(); jf.Append(_keywordName); } else { jf.Append(','); jf.AppendNewLine(); } foreach (var kvp in this.NavMembers) { index++; string key = kvp.Key; MemberExpression m = kvp.Value; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetInvokerAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Acceptable()) { innerKey = m.Expression.NodeType == ExpressionType.Parameter ? (m.Expression as ParameterExpression).Name : (m.Expression as MemberExpression).Member.Name; } else { MemberExpression mLeft = null; if (m.Expression.NodeType == ExpressionType.MemberAccess) { mLeft = m.Expression as MemberExpression; } else if (m.Expression.NodeType == ExpressionType.Call) { mLeft = (m.Expression as MethodCallExpression).Object as MemberExpression; } string name = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableName; innerAlias = _aliases.GetJoinTableAlias(name); if (string.IsNullOrEmpty(innerAlias)) { string keyLeft = mLeft.GetKeyWidthoutAnonymous(); if (this.NavMembers.ContainsKey(keyLeft)) { innerKey = keyLeft; } } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey); string alias2 = _aliases.GetTableAlias(outerKey); // 补充与USING字符串同等间距的空白 if (_aliases.ObviousAlias > 1 || index > 0) { jf.Append(" "); } Type type = m.Type; var typeRumtime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type); if (type.IsGenericType) { type = type.GetGenericArguments()[0]; } jf.Append(' '); jf.AppendMember(typeRumtime2.TableName, typeRumtime2.IsTemporary); jf.Append(' '); jf.Append(alias2); if (_onPhrase.Length > 0) { _onPhrase.Append(" AND "); } for (int i = 0; i < attribute.InnerKeys.Length; i++) { _onPhrase.Append(alias1); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.InnerKeys[i]); _onPhrase.Append(" = "); _onPhrase.Append(alias2); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.OuterKeys[i]); } if (index < this.NavMembers.Count - 1) { jf.Append(','); jf.AppendNewLine(); } } }
/// <summary> /// 初始化 <see cref="HavingExpressionVisitor"/> 类的新实例 /// </summary> public HavingExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, DbExpression having, DbExpression groupBy) : base(provider, aliases, having != null && having.Expressions != null ? having.Expressions[0] : null) { _groupBy = groupBy; _aliases = aliases; }
// LEFT OR INNER JOIN private void AppendLfInJoin(ISqlBuilder jf, ISqlBuilder wf, ISqlBuilder on, DbExpression exp, TableAliasCache aliases) { bool useExists = false; LambdaExpression left = exp.Expressions[1] as LambdaExpression; LambdaExpression right = exp.Expressions[2] as LambdaExpression; NewExpression body1 = left.Body as NewExpression; NewExpression body2 = right.Body as NewExpression; // t0(t1) string alias = body1 == null ? aliases.GetTableAlias(exp.Expressions[2]) : aliases.GetTableAlias(right.Parameters[0]);//(body2.Arguments[0]); IDbQueryable sQuery = (IDbQueryable)((exp.Expressions[0] as ConstantExpression).Value); if (sQuery.DbExpressions.Count == 1 && sQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable) { useExists = true; if ((wf != null && wf.Length > 0) || (on != null && on.Length > 0)) { wf.AppendNewLine(); if (wf != null && wf.Length > 0) { wf.Append("AND "); } } wf.Append("EXISTS("); wf.Indent += 1; wf.AppendNewLine(); wf.Append("SELECT 1 FROM "); Type type = exp.Expressions[0].Type.GetGenericArguments()[0]; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); wf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); wf.Append(' '); wf.Append(alias); wf.AppendNewLine(); wf.Append("WHERE "); } else { useExists = true; if ((wf != null && wf.Length > 0) || (on != null && on.Length > 0)) { wf.AppendNewLine(); if (wf != null && wf.Length > 0) { wf.Append("AND "); } } wf.Append("EXISTS("); wf.Indent += 1; wf.AppendNewLine(); wf.Append("SELECT 1 FROM("); var cmd2 = sQuery.Resolve(wf.Indent + 1, false, wf.Parameters); wf.Append(cmd2.CommandText); wf.AppendNewLine(); wf.Append(')'); wf.Append(' '); wf.Append(alias); wf.Append(" WHERE "); } ISqlBuilder builder = useExists ? wf : on; if (body1 == null) { builder.AppendMember(aliases, left.Body.ReduceUnary()); builder.Append(" = "); builder.AppendMember(aliases, right.Body.ReduceUnary()); } else { for (int index = 0; index < body1.Arguments.Count; ++index) { builder.AppendMember(aliases, body1.Arguments[index]); builder.Append(" = "); builder.AppendMember(aliases, body2.Arguments[index]); if (index < body1.Arguments.Count - 1) { builder.Append(" AND "); } } } //if (_where != null && _where.Expressions != null) this.AppendWhere(builder, right); if (useExists) { wf.Indent -= 1; wf.AppendNewLine(); wf.Append(')'); } }
// Cross Join private void AppendCrossJoin(ISqlBuilder jf, DbExpression exp, TableAliasCache aliases) { throw new NotSupportedException("Oracle not support."); }
// LEFT OR INNER JOIN private void AppendLfInJoin(ISqlBuilder builder, DbExpression exp, TableAliasCache aliases) { builder.Append(' '); IDbQueryable sQuery = (IDbQueryable)((exp.Expressions[0] as ConstantExpression).Value); if (sQuery.DbExpressions.Count == 1 && sQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable) { Type type = exp.Expressions[0].Type.GetGenericArguments()[0]; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); } else { // 嵌套 var cmd = sQuery.Resolve(builder.Indent + 1, false, builder.Parameters); builder.Append("("); builder.AppendNewLine(cmd.CommandText); builder.Append(')'); } LambdaExpression left = exp.Expressions[1] as LambdaExpression; LambdaExpression right = exp.Expressions[2] as LambdaExpression; // t0(t1) string alias = !(left.Body.NodeType == ExpressionType.New || left.Body.NodeType == ExpressionType.MemberInit) ? aliases.GetTableAlias(exp.Expressions[2]) : aliases.GetTableAlias(right.Parameters[0]);//(body2.Arguments[0]); builder.Append(' '); builder.Append(alias); builder.Append(' '); // ON a.Name = b.Name AND a.Id = b.Id builder.Append("ON "); if (left.Body.NodeType == ExpressionType.New) { NewExpression body1 = left.Body as NewExpression; NewExpression body2 = right.Body as NewExpression; for (int index = 0; index < body1.Arguments.Count; ++index) { builder.AppendMember(aliases, body1.Arguments[index]); builder.Append(" = "); builder.AppendMember(aliases, body2.Arguments[index]); if (index < body1.Arguments.Count - 1) { builder.Append(" AND "); } } } else if (left.Body.NodeType == ExpressionType.MemberInit) { MemberInitExpression body1 = left.Body as MemberInitExpression; MemberInitExpression body2 = right.Body as MemberInitExpression; for (int index = 0; index < body1.Bindings.Count; ++index) { builder.AppendMember(aliases, (body1.Bindings[index] as MemberAssignment).Expression); builder.Append(" = "); builder.AppendMember(aliases, (body2.Bindings[index] as MemberAssignment).Expression); if (index < body1.Bindings.Count - 1) { builder.Append(" AND "); } } } else { builder.AppendMember(aliases, left.Body.ReduceUnary()); builder.Append(" = "); builder.AppendMember(aliases, right.Body.ReduceUnary()); } }
// 添加导航属性关联 protected virtual void AppendNavigation() { if (this._navMembers == null || this._navMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HaveListNavigation) { _aliases = new TableAliasCache(_aliases.ObviousAlias); } //开始产生LEFT JOIN 子句 ISqlBuilder builder = this.JoinFragment; foreach (var kvp in _navMembers) { string key = kvp.Key; MemberExpression m = kvp.Value; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetInvokerAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Acceptable()) { innerKey = m.Expression.NodeType == ExpressionType.Parameter ? (m.Expression as ParameterExpression).Name : (m.Expression as MemberExpression).Member.Name; } else { MemberExpression mLeft = null; if (m.Expression.NodeType == ExpressionType.MemberAccess) { mLeft = m.Expression as MemberExpression; } else if (m.Expression.NodeType == ExpressionType.Call) { mLeft = (m.Expression as MethodCallExpression).Object as MemberExpression; } string name = TypeRuntimeInfoCache.GetRuntimeInfo(mLeft.Type).TableName; innerAlias = _aliases.GetJoinTableAlias(name); if (string.IsNullOrEmpty(innerAlias)) { string keyLeft = mLeft.GetKeyWidthoutAnonymous(); if (_navMembers.ContainsKey(keyLeft)) { innerKey = keyLeft; } } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey); string alias2 = _aliases.GetTableAlias(outerKey); builder.AppendNewLine(); builder.Append("LEFT JOIN "); Type type = m.Type; if (type.IsGenericType) { type = type.GetGenericArguments()[0]; } var typeRuntime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type); builder.AppendMember(typeRuntime2.TableName, !typeRuntime2.IsTemporary); builder.Append(" "); builder.Append(alias2); builder.Append(" ON "); for (int i = 0; i < attribute.InnerKeys.Length; i++) { builder.Append(alias1); builder.Append('.'); builder.AppendMember(attribute.InnerKeys[i]); builder.Append(" = "); builder.Append(alias2); builder.Append('.'); builder.AppendMember(attribute.OuterKeys[i]); if (i < attribute.InnerKeys.Length - 1) { builder.Append(" AND "); } } } }
/// <summary> /// 初始化 <see cref="NpgUpdateExpressionVisitor"/> 类的新实例 /// </summary> public NpgUpdateExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, Expression exp) : base(provider, aliases, exp) { _provider = provider; _aliases = aliases; }
/// <summary> /// 追加列名 /// </summary> /// <param name="expression">列名表达式</param> /// <param name="aliases">表别名</param> /// <returns>返回解析到的表别名</returns> public Expression AppendMember(Expression expression, TableAliasCache aliases) { this.AppendMember(aliases, expression); return(expression); }
/// <summary> /// 初始化 <see cref="GroupByExpressionVisitor"/> 类的新实例 /// </summary> public GroupByExpressionVisitor(IDbQueryProvider provider, TableAliasCache aliases, DbExpression groupBy) : base(provider, aliases, groupBy != null ? groupBy.Expressions[0] : null, false) { }