/// <summary> /// 初始化 <see cref="ColumnExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="dbQuery">查询语义</param> public ColumnExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, IDbQueryableInfo_Select dbQuery) : base(provider, aliases, dbQuery.Select.Expressions != null ? dbQuery.Select.Expressions[0] : null) { _provider = provider; _aliases = aliases; _dbQuery = dbQuery; _groupBy = dbQuery.GroupBy; _include = dbQuery.Includes; if (_pickColumns == null) { _pickColumns = new DbColumnCollection(); } _navDescriptors = new NavDescriptorCollection(); _navDescriptorKeys = new List <string>(10); }
/// <summary> /// 初始化 <see cref="NpgJoinExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="joins">JOIN 子句</param> /// <param name="dbExpressionType">表达式类型</param> public NpgJoinExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, List <DbExpression> joins, DbExpressionType dbExpressionType) : base(provider, aliases, joins) { _qJoin = joins; _aliases = aliases; _provider = provider; _dbExpressionType = dbExpressionType; if (_dbExpressionType == DbExpressionType.Delete) { _keywordName = "USING "; } else if (_dbExpressionType == DbExpressionType.Update) { _keywordName = "FROM "; } _pad = "".PadLeft(_keywordName.Length, ' '); }
/// <summary> /// 实例化 <see cref="NpgMappingDbCommand" /> 的新实例 /// </summary> /// <param name="provider">数据查询提供者</param> /// <param name="aliases">别名</param> /// <param name="dbExpressionType">表达式类型</param> /// <param name="token">解析上下文参数</param> public NpgMappingDbCommand(IDbQueryProvider provider, TableAlias aliases, DbExpressionType dbExpressionType, ResolveToken token) : base(provider, aliases, token) { _provider = provider; _aliases = aliases; _onPhrase = _provider.CreateSqlBuilder(token); _dbExpressionType = dbExpressionType; if (_dbExpressionType == DbExpressionType.Delete) { _keywordName = "USING "; } else if (_dbExpressionType == DbExpressionType.Update) { _keywordName = "FROM "; } _pad = "".PadLeft(_keywordName.Length, ' '); }
/// <summary> /// 生成关联子句所表示的别名列表 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected TableAlias PrepareTableAlias(IDbQueryableInfo_Select dbQuery, ResolveToken token) { var aliases = new TableAlias((dbQuery.Joins != null ? dbQuery.Joins.Count : 0) + 1, token != null ? token.AliasPrefix : null); foreach (DbExpression exp in dbQuery.Joins) { // [INNER/LEFT JOIN] if (exp.DbExpressionType == DbExpressionType.GroupJoin || exp.DbExpressionType == DbExpressionType.Join || exp.DbExpressionType == DbExpressionType.GroupRightJoin) { this.PrepareJoinAlias(exp, aliases); } else if (exp.DbExpressionType == DbExpressionType.SelectMany) { this.PrepareCrossAlias(exp, aliases); } } return(aliases); }
// Cross Join private void AppendCrossJoin(ISqlBuilder builder, DbExpression exp, TableAlias aliases) { var lambdaExp = exp.Expressions[1] as LambdaExpression; Type type = lambdaExp.Parameters[1].Type; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); bool withNoLock = !typeRuntime.IsTemporary && _context.NoLock && !string.IsNullOrEmpty(_provider.WidthNoLock); builder.Append(' '); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); string alias = aliases.GetTableAlias(lambdaExp.Parameters[1]); builder.Append(' '); builder.Append(alias); builder.Append(' '); if (withNoLock) { builder.Append(_provider.WidthNoLock); builder.Append(' '); } }
// LEFT OR INNER JOIN private void AppendLfInJoin(ISqlBuilder builder, DbExpression dbExpression, TableAlias aliases) { bool withNoLock = false; builder.Append(' '); IDbQueryable dbQuery = (IDbQueryable)((dbExpression.Expressions[0] as ConstantExpression).Value); if (dbQuery.DbExpressions.Count == 1 && dbQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable) { Type type = dbExpression.Expressions[0].Type.GetGenericArguments()[0]; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); withNoLock = !typeRuntime.IsTemporary && _context.NoLock && !string.IsNullOrEmpty(_provider.WidthNoLock); } else { // 嵌套 var cmd = dbQuery.Resolve(builder.Indent + 1, false, builder.Token); builder.Append("("); builder.Append(cmd.CommandText); builder.AppendNewLine(); builder.Append(')'); } var left = dbExpression.Expressions[1] as LambdaExpression; var right = dbExpression.Expressions[2] as LambdaExpression; // t0(t1) string alias = !(left.Body.NodeType == ExpressionType.New || left.Body.NodeType == ExpressionType.MemberInit) ? aliases.GetTableAlias(dbExpression.Expressions[2]) : aliases.GetTableAlias(right.Parameters[0]); builder.Append(' '); builder.Append(alias); builder.Append(' '); if (withNoLock) { builder.Append(_provider.WidthNoLock); builder.Append(' '); } // ON a.Name = b.Name AND a.Id = b.Id builder.Append("ON "); if (left.Body.NodeType == ExpressionType.New) { var body1 = left.Body as NewExpression; var 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) { var body1 = left.Body as MemberInitExpression; var 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()); } }
/// <summary> /// 初始化 <see cref="SqlServerJoinExpressionVisitor"/> 类的新实例 /// </summary> internal SqlServerJoinExpressionVisitor(SqlClient.SqlServerDbContext context, TableAlias aliases, List <DbExpression> joins) : base(context.Provider, aliases, joins) { _joins = joins; _aliases = aliases; _context = context; _provider = context.Provider as SqlClient.SqlServerDbQueryProvider; }
/// <summary> /// 初始化 <see cref="NavPredicateExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="predicate">要访问的表达式</param> /// <param name="alias">指定的表别名</param> public NavPredicateExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, Expression predicate, string alias) : base(provider, aliases, predicate) { _expression = base.Expression; _alias = alias; }
/// <summary> /// 初始化 <see cref="OracleUpdateExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="expression">要访问的表达式</param> public OracleUpdateExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, Expression expression) : base(provider, aliases, expression) { _provider = provider; _aliases = aliases; }
/// <summary> /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="groupBy">GROUP BY 子句</param> public GroupByExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, DbExpression groupBy) : base(provider, aliases, groupBy != null ? groupBy.Expressions[0] : null) { }
/// <summary> /// 初始化 <see cref="OracleColumnExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="dbQuery">查询语义</param> public OracleColumnExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, IDbQueryableInfo_Select dbQuery) : base(provider, aliases, dbQuery) { _dbQuery = dbQuery; }
// 获取 LEFT JOIN / INNER JOIN 子句关联表的的别名 private void PrepareJoinAlias(DbExpression dbExpression, TableAlias aliases) { Type type = dbExpression.Expressions[0].Type.GetGenericArguments()[0]; string name = TypeRuntimeInfoCache.GetRuntimeInfo(type).TableName; string outerAlias = null; // on a.Name equals b.Name 或 on new{ Name = a.Name,Id=a.Id } equals new { Name = b.Name,Id=b.Id } var left = dbExpression.Expressions[1] as LambdaExpression; var right = dbExpression.Expressions[2] as LambdaExpression; if (left.Body.NodeType == ExpressionType.New) { var body1 = left.Body as NewExpression; var 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]); outerAlias = alias; // 记录显示指定的LEFT JOIN 表别名 aliases.AddJoinTableAlias(name, alias); } } else if (left.Body.NodeType == ExpressionType.MemberInit) { var body1 = left.Body as MemberInitExpression; var 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); outerAlias = alias; // 记录显示指定的LEFT JOIN 表别名 aliases.AddJoinTableAlias(name, alias); } } else { aliases.GetTableAlias(dbExpression.Expressions[1]); string alias = aliases.GetTableAlias(dbExpression.Expressions[2]); outerAlias = alias; // 记录显示指定的LEFT JOIN 表别名 aliases.AddJoinTableAlias(name, alias); } // 由 GetTable 重载指定的导航属性表别名 if (dbExpression.Expressions.Length > 4) { if (string.IsNullOrEmpty(outerAlias) || outerAlias == TableAlias.ALIASNULL) { var lambda = dbExpression.Expressions[3] as LambdaExpression; string alias = aliases.GetTableAlias(lambda.Parameters[1]); outerAlias = alias; // 记录显示指定的LEFT JOIN 表别名 aliases.AddJoinTableAlias(name, alias); } var member = (dbExpression.Expressions[4] as LambdaExpression).Body as MemberExpression; string keyId = member.GetKeyWidthoutAnonymous(); // 记录GetTable<,>(path)指定的表别名 aliases.AddGetTableAlias(keyId, outerAlias); } }
// 添加导航属性关联 protected override void ResoveNavMember() { if (base.NavMembers == null || base.NavMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HasMany) { _aliases = new TableAlias(_aliases.HoldQty); } //开始产生LEFT JOIN 子句 ISqlBuilder builder = this.JoinFragment; foreach (var nav in base.NavMembers) { string key = nav.KeyId; MemberExpression m = nav.Expression; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetMemberAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Visitable()) { 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 (base.NavMembers.Contains(keyLeft)) { innerKey = keyLeft; } innerAlias = _aliases.GetNavTableAlias(innerKey); } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey); string alias2 = _aliases.GetNavTableAlias(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); bool withNoLock = !typeRuntime2.IsTemporary && _context.NoLock && !string.IsNullOrEmpty(_provider.WidthNoLock); if (withNoLock) { builder.Append(' '); builder.Append(_provider.WidthNoLock); } builder.Append(" ON "); for (int i = 0; i < attribute.InnerKeys.Length; i++) { if (attribute.InnerKeys[i].StartsWith(Constant.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { builder.Append(attribute.InnerKeys[i].Substring(7)); } else { builder.Append(alias1); builder.Append('.'); builder.AppendMember(attribute.InnerKeys[i]); } builder.Append(" = "); if (attribute.OuterKeys[i].StartsWith(Constant.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { builder.Append(attribute.OuterKeys[i].Substring(7)); } else { builder.Append(alias2); builder.Append('.'); builder.AppendMember(attribute.OuterKeys[i]); } if (i < attribute.InnerKeys.Length - 1) { builder.Append(" AND "); } } if (nav.Predicate != null) { string alias = _aliases.GetNavTableAlias(nav.KeyId); var visitor = new NavPredicateExpressionVisitor(_provider, _aliases, nav.Predicate, alias); visitor.Write(builder); } } }
// LEFT OR INNER JOIN private void AppendLfInJoin(ISqlBuilder jf, ISqlBuilder on, DbExpression dbExpression, TableAlias aliases) { IDbQueryable sQuery = (IDbQueryable)((dbExpression.Expressions[0] as ConstantExpression).Value); if (!usedKeyword) { jf.AppendNewLine(); jf.Append(_keywordName); usedKeyword = true; } else { jf.Append(','); jf.AppendNewLine(); jf.Append(_pad); } if (sQuery.DbExpressions.Count == 1 && sQuery.DbExpressions[0].DbExpressionType == DbExpressionType.GetTable) { Type type = dbExpression.Expressions[0].Type.GetGenericArguments()[0]; var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(type); jf.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); } else { // 嵌套 var cmd = sQuery.Resolve(jf.Indent + _dbExpressionType == DbExpressionType.Delete ? 2 : 1, false, jf.Token); jf.Append("( "); jf.Append(_dbExpressionType == DbExpressionType.Delete ? cmd.CommandText.TrimStart() : cmd.CommandText); jf.Append(')'); } LambdaExpression left = dbExpression.Expressions[1] as LambdaExpression; LambdaExpression right = dbExpression.Expressions[2] as LambdaExpression; // t0(t1) string alias = !(left.Body.NodeType == ExpressionType.New || left.Body.NodeType == ExpressionType.MemberInit) ? aliases.GetTableAlias(dbExpression.Expressions[2]) : aliases.GetTableAlias(right.Parameters[0]); jf.Append(' '); jf.Append(alias); if (on.Length > 0) { on.Append(" AND "); } 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) { on.AppendMember(aliases, body1.Arguments[index]); on.Append(" = "); on.AppendMember(aliases, body2.Arguments[index]); if (index < body1.Arguments.Count - 1) { on.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) { on.AppendMember(aliases, (body1.Bindings[index] as MemberAssignment).Expression); on.Append(" = "); on.AppendMember(aliases, (body2.Bindings[index] as MemberAssignment).Expression); if (index < body1.Bindings.Count - 1) { on.Append(" AND "); } } } else { on.AppendMember(aliases, left.Body.ReduceUnary()); on.Append(" = "); on.AppendMember(aliases, right.Body.ReduceUnary()); } }
/// <summary> /// 追加列名 /// </summary> /// <param name="expression">列名表达式</param> /// <param name="aliases">表别名</param> /// <returns>返回解析到的表别名</returns> public Expression AppendMember(Expression expression, TableAlias aliases) { this.AppendMember(aliases, expression); return(expression); }
/// <summary> /// 初始化 <see cref="NpgWhereExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="dbExpression">要访问的表达式</param> public NpgWhereExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, DbExpression dbExpression) : base(provider, aliases, dbExpression) { _expression = dbExpression != null && dbExpression.Expressions != null ? dbExpression.Expressions[0] : null; }
/// <summary> /// 添加导航属性关联 /// </summary> protected override void ResoveNavMember() { if (this.NavMembers == null || this.NavMembers.Count == 0) { return; } // 如果有一对多的导航属性,肯定会产生嵌套查询。那么内层查询别名肯定是t0,所以需要清掉 if (this.HasMany) { _aliases = new TableAlias(_aliases.HoldQty); } //开始产生 USING 子句 ISqlBuilder jf = this.JoinFragment; int index = -1; // 未生成USING子句 if (_aliases.HoldQty <= 1) { jf.AppendNewLine(); jf.Append(_keywordName); } else { jf.Append(','); jf.AppendNewLine(); } foreach (var nav in this.NavMembers) { index++; string key = nav.KeyId; MemberExpression m = nav.Expression; TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo(m.Expression.Type); ForeignKeyAttribute attribute = typeRuntime.GetMemberAttribute <ForeignKeyAttribute>(m.Member.Name); string innerKey = string.Empty; string outerKey = key; string innerAlias = string.Empty; if (!m.Expression.Visitable()) { 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.Contains(keyLeft)) { innerKey = keyLeft; } innerAlias = _aliases.GetNavTableAlias(innerKey); } } string alias1 = !string.IsNullOrEmpty(innerAlias) ? innerAlias : _aliases.GetTableAlias(innerKey); string alias2 = _aliases.GetNavTableAlias(outerKey); // 补充与USING字符串同等间距的空白 if (_aliases.HoldQty > 1 || index > 0) { jf.Append(_pad); } Type type = m.Type; var typeRumtime2 = TypeRuntimeInfoCache.GetRuntimeInfo(type); if (type.IsGenericType) { type = type.GetGenericArguments()[0]; } 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++) { if (attribute.InnerKeys[i].StartsWith(Constant.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { _onPhrase.Append(attribute.InnerKeys[i].Substring(7)); } else { _onPhrase.Append(alias1); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.InnerKeys[i]); } _onPhrase.Append(" = "); if (attribute.OuterKeys[i].StartsWith(Constant.CONSTANT_FOREIGNKEY, StringComparison.Ordinal)) { _onPhrase.Append(attribute.OuterKeys[i].Substring(7)); } else { _onPhrase.Append(alias2); _onPhrase.Append('.'); _onPhrase.AppendMember(attribute.OuterKeys[i]); } } if (nav.Predicate != null) { string alias = _aliases.GetNavTableAlias(nav.KeyId); var visitor = new NavPredicateExpressionVisitor(_provider, _aliases, nav.Predicate, alias); visitor.Write(_onPhrase); } if (index < this.NavMembers.Count - 1) { jf.Append(','); jf.AppendNewLine(); } } }
/// <summary> /// 初始化 <see cref="HavingExpressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="aliases">表别名集合</param> /// <param name="having">HAVING 子句</param> /// <param name="groupBy">GROUP BY 子句</param> public HavingExpressionVisitor(IDbQueryProvider provider, TableAlias aliases, DbExpression having, DbExpression groupBy) : base(provider, aliases, having != null && having.Expressions != null ? having.Expressions[0] : null) { _groupBy = groupBy; _aliases = aliases; }