/// <summary> /// 实例化 <see cref="MethodCallExressionVisitor"/> 类的新实例 /// </summary> public MethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor) { _provider = provider; _visitor = visitor; _builder = visitor.SqlBuilder; _visitedMember = _visitor.VisitedMember; }
/// <summary> /// 访问表示方法调用的节点 /// </summary> /// <param name="node">方法调用节点</param> /// <param name="visitor">访问器</param> /// <returns></returns> public override Expression VisitMethodCall(MethodCallExpression node, ExpressionVisitorBase visitor) { Type type = node.Object != null ? node.Object.Type : node.Arguments[0].Type; string methodName = string.Empty; if (type == typeof(string) || node.Method.Name == "ToString") { methodName = "VisitStrMethodCall_"; } else if (typeof(System.Collections.IEnumerable).IsAssignableFrom(type)) { methodName = "VisitEnumMethodCall_"; } if (!string.IsNullOrEmpty(methodName)) { MemberAccess_Method invoker = null; MethodCallExressionVisitor._methods.TryGetValue(methodName + node.Method.Name, out invoker); if (invoker != null) { object exp = invoker.Invoke(this, new object[] { node, visitor }); return(exp as Expression); } } throw new XfwException("{0}.{1} is not supported.", node.Method.DeclaringType, node.Method.Name); }
private Expression VisitStrMethodCall_SubString(MethodCallExpression m, ExpressionVisitorBase visitor) { if (m != null) { List <Expression> args = new List <Expression>(m.Arguments); if (m.Object != null) { args.Insert(0, m.Object); } visitor.Append("SUBSTRING("); visitor.Visit(args[0]); visitor.Append(","); visitor.Visit(args[1]); visitor.Append(" + 1,"); if (args.Count == 3) { visitor.Visit(args[2]); } else { visitor.Append("LEN("); visitor.Visit(args[0]); visitor.Append(")"); } visitor.Append(")"); } return(m); }
private Expression VisitStrMember_Length(MemberExpression m, ExpressionVisitorBase visitor) { visitor.Append("LEN("); visitor.Visit(m.Expression); visitor.Append(")"); return(m); }
/// <summary> /// 实例化 <see cref="OracleMethodCallExressionVisitor"/> 类的新实例 /// </summary> public OracleMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor) : base(provider, visitor) { _provider = provider; _visitor = visitor; _builder = visitor.SqlBuilder; _visitedMark = _visitor.VisitedMark; }
private Expression VisitStrMethodCall_ToString(MethodCallExpression m, ExpressionVisitorBase visitor) { visitor.Append("CAST("); visitor.Visit(m.Object != null ? m.Object : m.Arguments[0]); visitor.Append(" AS VARCHAR)"); return(m); }
// 创建 DELETE 命令 protected override CommandDefine ParseDeleteCommand <T>(DbQueryableInfo_Delete <T> qDelete) { var rInfo = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); SqlBuilder builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight); bool useKey = false; builder.Append("DELETE t0 FROM "); builder.AppendMember(rInfo.TableName); builder.Append(" t0 "); if (qDelete.Entity != null) { object entity = qDelete.Entity; builder.AppendNewLine(); builder.Append("WHERE "); foreach (var kv in rInfo.Wrappers) { var wrapper = kv.Value as MemberAccessWrapper; var column = wrapper.Column; if (column != null && column.IsKey) { useKey = true; var value = wrapper.Get(entity); var seg = ExpressionVisitorBase.GetSqlValue(value); builder.AppendMember("t0", wrapper.Member.Name); builder.Append(" = "); builder.Append(seg); builder.Append(" AND "); } ; } builder.Length -= 5; if (!useKey) { throw new XfwException("Delete<T>(T value) require T must have key column."); } } else if (qDelete.SelectInfo != null) { TableAliasCache aliases = this.PrepareAlias <T>(qDelete.SelectInfo); var sc = new CommandDefine_Select.Builder(this.EscCharLeft, this.EscCharRight, aliases); ExpressionVisitorBase visitor = new JoinExpressionVisitor(this, aliases, qDelete.SelectInfo.Join); visitor.Write(sc.JoinFragment); visitor = new WhereExpressionVisitor(this, aliases, qDelete.SelectInfo.Where); visitor.Write(sc.WhereFragment); sc.AddNavigation(visitor.Navigations); builder.Append(sc.Command); } return(new CommandDefine(builder.ToString(), null, System.Data.CommandType.Text)); //builder.ToString(); }
/// <summary> /// 实例化 <see cref="SqlServerMethodCallExressionVisitor"/> 类的新实例 /// </summary> /// <param name="provider">查询语义提供者</param> /// <param name="visitor">表达式访问器</param> public MySqlMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor) : base(provider, visitor) { _provider = provider; _visitor = visitor; _builder = visitor.SqlBuilder; _visitedMark = _visitor.VisitedStack; _dbValue = _provider.DbValue; }
private Expression VisitStrMethodCall_Trim(MethodCallExpression m, ExpressionVisitorBase visitor) { if (m != null) { visitor.Append("RTRIM(LTRIM("); visitor.Visit(m.Object != null ? m.Object : m.Arguments[0]); visitor.Append("))"); } return(m); }
/// <summary> /// 访问表示 null 合并运算的节点 a ?? b /// </summary> /// <param name="b">二元表达式节点</param> /// <param name="visitor">访问器</param> /// <returns></returns> public override Expression VisitCoalesce(BinaryExpression b, ExpressionVisitorBase visitor) { // expression like a.Name ?? "TAN" => ISNULL(a.Name,'TAN') visitor.Append("ISNULL("); visitor.Visit(b.Left is ConstantExpression ? b.Right : b.Left); visitor.Append(","); visitor.Visit(b.Left is ConstantExpression ? b.Left : b.Right); visitor.Append(")"); return(b); }
/// <summary> /// 访问表示 null 判断运算的节点 a.Name == null /// </summary> /// <param name="b">二元表达式节点</param> /// <param name="ExpressionVisitorBase">访问器</param> /// <returns></returns> public override Expression VisitEqualNull(BinaryExpression b, ExpressionVisitorBase visitor) { // a.Name == null => a.Name Is Null string oper = b.NodeType == ExpressionType.Equal ? " IS " : " IS NOT "; visitor.Visit(b.Left is ConstantExpression ? b.Right : b.Left); visitor.Append(oper); visitor.Visit(b.Left is ConstantExpression ? b.Left : b.Right); return(b); }
private Expression VisitEnumMethodCall_Contains(MethodCallExpression m, ExpressionVisitorBase visitor) { if (m == null) { return(m); } MemberExpression member = m.Arguments[m.Arguments.Count - 1] as MemberExpression; visitor.Visit(m.Arguments[m.Arguments.Count - 1]); visitor.Append(" IN("); //ConstantExpression constExpr = (m.Object != null ? m.Object : m.Arguments[0]) as ConstantExpression; //visitor.Visit(constExpr); Expression exp = m.Object != null ? m.Object : m.Arguments[0]; if (exp.NodeType == ExpressionType.Constant) { visitor.Visit(exp); } else if (exp.NodeType == ExpressionType.MemberAccess) { visitor.Visit(exp.Evaluate()); } else if (exp.NodeType == ExpressionType.NewArrayInit) { var expressions = (exp as NewArrayExpression).Expressions; for (int i = 0; i < expressions.Count; i++) { visitor.Visit(expressions[i]); if (i < expressions.Count - 1) { visitor.Append(","); } } } visitor.Append(")"); return(m); }
/// <summary> /// 访问表示字段或者属性的属性的节点 a.Name.Length /// </summary> /// <param name="node">字段或者属性节点</param> /// <param name="visitor">访问器</param> /// <returns></returns> public override Expression VisitMemberMember(MemberExpression node, ExpressionVisitorBase visitor) { Type type = node.Expression.Type; string methodName = string.Empty; if (type == typeof(string)) { methodName = "VisitStrMember_"; } if (!string.IsNullOrEmpty(methodName)) { MemberAccess_Method invoker = null; MethodCallExressionVisitor._methods.TryGetValue(methodName + node.Member.Name, out invoker); if (invoker != null) { object exp = invoker.Invoke(this, new object[] { node, visitor }); return(exp as Expression); } } throw new XfwException("{0}.{1} is not supported.", node.Member.DeclaringType, node.Member.Name); }
private Expression VisitStrMethodCall_EndsWith(MethodCallExpression m, ExpressionVisitorBase visitor) { if (m != null) { visitor.Visit(m.Object); visitor.Append(" LIKE "); if (m.Arguments[0].NodeType == ExpressionType.Constant) { ConstantExpression c = m.Arguments[0] as ConstantExpression; //visitor.Append(string.Format("N'%{0}'", c.Value)); visitor.Append("N'%"); visitor.Append(c.Value != null ? c.Value.ToString() : string.Empty); visitor.Append("'"); } else { visitor.Append("('%' + "); visitor.Visit(m.Arguments[0]); visitor.Append(")"); } } return(m); }
/// <summary> /// 创建 UPDATE 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveUpdateCommand <T>(IDbQueryableInfo_Update dbQuery, ResolveToken token) { var context = (SqlServerDbContext)token.DbContext; ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE t0 SET"); builder.AppendNewLine(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder seg_Where = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var m in typeRuntime.Members) { var column = m.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // Fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (m.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp) { continue; // 行版本号 } if (m.ForeignKey != null) { continue; } if (m.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember("t0", m.Member.Name); builder.Append(" = "); gotoLabel: var value = m.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); if (column == null || !column.IsIdentity) { builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; seg_Where.AppendMember("t0", m.Member.Name); seg_Where.Append(" = "); seg_Where.Append(seg); seg_Where.Append(" AND "); } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require entity must have key column."); } builder.Length = length; seg_Where.Length -= 5; builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0"); builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(seg_Where); } else if (dbQuery.Expression != null) { TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token); ExpressionVisitorBase visitor = null; visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression); visitor.Write(builder); builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.AppendAs("t0"); var cmd = new SqlServerMappingCommand(context, aliases, token) { HasMany = dbQuery.Query.HasMany }; visitor = new SqlServerJoinExpressionVisitor(context, aliases, dbQuery.Query.Joins); visitor.Write(cmd.JoinFragment); visitor = new WhereExpressionVisitor(this, aliases, dbQuery.Query.Where); visitor.Write(cmd.WhereFragment); cmd.AddNavMembers(visitor.NavMembers); builder.Append(cmd.CommandText); } return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
// 创建 UPDATE 命令 protected override DbCommandDefinition ParseUpdateCommand <T>(DbQueryableInfo_Update <T> uQuery, List <IDbDataParameter> parameters = null) { ISqlBuilder builder = this.CreateSqlBuilder(parameters); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0 SET"); builder.AppendNewLine(); if (uQuery.Entity != null) { object entity = uQuery.Entity; ISqlBuilder whereBuilder = this.CreateSqlBuilder(builder.Parameters); bool useKey = false; int length = 0; foreach (var kv in typeRuntime.Invokers) { MemberInvokerBase invoker = kv.Value; var column = invoker.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (invoker.ForeignKey != null) { continue; } if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember(invoker.Member.Name); builder.Append(" = "); gotoLabel: if (column == null || !column.IsIdentity) { var value = invoker.Invoke(entity); var seg = builder.GetSqlValueWidthDefault(value, column); builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require T must have key column."); } // ORACLE 需要注意参数顺序问题 int index = -1; foreach (var kv in typeRuntime.KeyInvokers) { MemberInvokerBase invoker = kv.Value; var column = invoker.Column; var value = invoker.Invoke(entity); var seg = builder.GetSqlValueWidthDefault(value, column); index += 1; whereBuilder.AppendMember(invoker.Member.Name); whereBuilder.Append(" = "); whereBuilder.Append(seg); if (index < typeRuntime.KeyInvokers.Count - 1) { whereBuilder.Append(" AND "); } } builder.Length = length; builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(whereBuilder); } else if (uQuery.Expression != null) { TableAliasCache aliases = this.PrepareAlias <T>(uQuery.SelectInfo); ExpressionVisitorBase visitor = null; visitor = new OracleUpdateExpressionVisitor(this, aliases, uQuery.Expression); visitor.Write(builder); var cmd2 = new OracleDbCommandDefinition_Delete(this, aliases, builder.Parameters); cmd2.HaveListNavigation = uQuery.SelectInfo.HaveListNavigation; var visitor0 = new OracleJoinExpressionVisitor(this, aliases, uQuery.SelectInfo.Join, uQuery.SelectInfo.Where); visitor0.Write(cmd2); var visitor1 = new OracleWhereExpressionVisitor(this, aliases, uQuery.SelectInfo.Where); visitor1.Write(cmd2.WhereFragment); cmd2.AddNavMembers(visitor1.NavMembers); builder.Append(cmd2.CommandText); } builder.Append(';'); return(new DbCommandDefinition(builder.ToString(), builder.Parameters, System.Data.CommandType.Text)); }
/// <summary> /// 创建方法表达式访问器 /// </summary> /// <returns></returns> public override IMethodCallExressionVisitor CreateMethodCallVisitor(ExpressionVisitorBase visitor) { return(new OracleMethodCallExressionVisitor(this, visitor)); }
/// <summary> /// 实例化 <see cref="SqlMethodCallExressionVisitor"/> 类的新实例 /// </summary> public SqlMethodCallExressionVisitor(IDbQueryProvider provider, ExpressionVisitorBase visitor) : base(provider, visitor) { }
protected override IMappingObjectExpression VisitLambda(LambdaExpression exp) { this._lambda = exp; this._visitor = new GeneralExpressionVisitor(exp, this._moeList); return(this.Visit(exp.Body)); }
// 创建 UPDATE 命令 protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0 SET"); builder.AppendNewLine(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder whereBuilder = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var invoker in typeRuntime.Invokers) { var column = invoker.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (invoker.ForeignKey != null) { continue; } if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember(invoker.Member.Name); builder.Append(" = "); gotoLabel: var value = invoker.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); if (column == null || !column.IsIdentity) { builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; whereBuilder.AppendMember(invoker.Member.Name); whereBuilder.Append(" = "); whereBuilder.Append(seg); whereBuilder.Append(" AND "); } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require T must have key column."); } builder.Length = length; whereBuilder.Length -= 5; builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(whereBuilder); } else if (dbQuery.Expression != null) { TableAliasCache aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token); ExpressionVisitorBase visitor = null; visitor = new NpgUpdateExpressionVisitor(this, aliases, dbQuery.Expression); visitor.Write(builder); var cmd2 = new NpgMapperCommand(this, aliases, DbExpressionType.Update, token) { HasMany = dbQuery.SelectInfo.HasMany }; var visitor0 = new NpgJoinExpressionVisitor(this, aliases, dbQuery.SelectInfo.Joins, DbExpressionType.Update); visitor0.Write(cmd2); var visitor1 = new NpgWhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion); visitor1.Write(cmd2.WhereFragment); cmd2.AddNavMembers(visitor1.NavMembers); builder.Append(cmd2.CommandText); } builder.Append(';'); return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
protected override IMappingObjectExpression VisitLambda(LambdaExpression exp) { this._visitor = new GeneralExpressionParser(this._scopeParameters, this._scopeTables); return(this.Visit(exp.Body)); }
// 创建 UPDATE 命令 protected override Command ResolveUpdateCommand <T>(DbQueryableInfo_Update <T> dbQuery, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0 SET"); builder.AppendNewLine(); if (dbQuery.Entity != null) { object entity = dbQuery.Entity; ISqlBuilder whereBuilder = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var invoker in typeRuntime.Invokers) { var column = invoker.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (invoker.ForeignKey != null) { continue; } if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember(invoker.Member.Name); builder.Append(" = "); gotoLabel: if (column == null || !column.IsIdentity) { var value = invoker.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require T must have key column."); } // ORACLE 需要注意参数顺序问题 int index = -1; foreach (var invoker in typeRuntime.KeyInvokers) { var column = invoker.Column; var value = invoker.Invoke(entity); var seg = this.DbValue.GetSqlValueWidthDefault(value, token, column); index += 1; whereBuilder.AppendMember(invoker.Member.Name); whereBuilder.Append(" = "); whereBuilder.Append(seg); if (index < typeRuntime.KeyInvokers.Count - 1) { whereBuilder.Append(" AND "); } } builder.Length = length; builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(whereBuilder); } else if (dbQuery.Expression != null) { // SELECT 表达式 LambdaExpression lambda = dbQuery.Expression as LambdaExpression; var body = lambda.Body; Expression expression = null; if (body.NodeType == ExpressionType.MemberInit) { var memberInit = body as MemberInitExpression; var bindings = new List <MemberBinding>(memberInit.Bindings); foreach (var invoker in typeRuntime.KeyInvokers) { var member = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member); var binding = Expression.Bind(invoker.Member, member); if (!bindings.Any(x => x.Member == invoker.Member)) { bindings.Add(binding); } } expression = Expression.MemberInit(memberInit.NewExpression, bindings); } else if (body.NodeType == ExpressionType.New) { var newExpression = body as NewExpression; var bindings = new List <MemberBinding>(); for (int i = 0; i < newExpression.Members.Count; i++) { var invoker = typeRuntime.GetInvoker(newExpression.Members[i].Name); var binding = Expression.Bind(invoker.Member, newExpression.Arguments[i].Type != invoker.DataType ? Expression.Convert(newExpression.Arguments[i], invoker.DataType) : newExpression.Arguments[i]); bindings.Add(binding); } foreach (var invoker in typeRuntime.KeyInvokers) { var member = Expression.MakeMemberAccess(lambda.Parameters[0], invoker.Member); var binding = Expression.Bind(invoker.Member, member); if (!bindings.Any(x => x.Member == invoker.Member)) { bindings.Add(binding); } } var newExpression2 = Expression.New(typeRuntime.ConstructInvoker.Constructor); expression = Expression.MemberInit(newExpression2, bindings); } // 解析查询以确定是否需要嵌套 dbQuery.SelectInfo.Select = new DbExpression(DbExpressionType.Select, expression); var cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, null);//, token); if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.SelectInfo.Joins.Count > 0) { // 无法使用 DISTINCT, GROUP BY 等子句从视图中选择 ROWID 或采样。UPDATE 不能用rowid // 有导航属性或者关联查询,使用 MERGE INTO 语法。要求必须有主键 if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0) { throw new XFrameworkException("Update<T>(Expression<Func<T, object>> updateExpression) require entity must have key column."); } builder.Length = 0; builder.Append("MERGE INTO "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.AppendNewLine(" t0"); builder.Append("USING ("); cmd = (MapperCommand)this.ResolveSelectCommand <T>(dbQuery.SelectInfo, 1, false, token); builder.AppendNewLine(cmd.CommandText); builder.Append(") t1 ON ("); foreach (var invoker in typeRuntime.KeyInvokers) { builder.AppendMember("t0", invoker.Name); builder.Append(" = "); builder.AppendMember("t1", invoker.Name); builder.Append(" AND "); } builder.Length -= 5; builder.Append(')'); // UPDATE builder.AppendNewLine(); builder.AppendNewLine("WHEN MATCHED THEN UPDATE SET "); // SET 字段 var visitor = new OracleUpdateExpressionVisitor(this, null, dbQuery.Expression); visitor.Write(builder); } else { // 直接 SQL 的 UPDATE 语法 TableAliasCache aliases = this.PrepareTableAlias <T>(dbQuery.SelectInfo, token); ExpressionVisitorBase visitor = null; visitor = new UpdateExpressionVisitor(this, aliases, dbQuery.Expression); visitor.Write(builder); visitor = new WhereExpressionVisitor(this, aliases, dbQuery.SelectInfo.Condtion); visitor.Write(builder); } } builder.Append(';'); return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
// 创建 DELETE 命令 protected override Command ParseDeleteCommand <T>(DbQueryableInfo_Delete <T> dQueryInfo, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); TypeRuntimeInfo typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("DELETE FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" "); if (dQueryInfo.Entity != null) { if (typeRuntime.KeyInvokers == null || typeRuntime.KeyInvokers.Count == 0) { throw new XFrameworkException("Delete<T>(T value) require entity must have key column."); } object entity = dQueryInfo.Entity; builder.AppendNewLine(); builder.Append("WHERE "); foreach (var invoker in typeRuntime.KeyInvokers) { var column = invoker.Column; var value = invoker.Invoke(entity); var seg = this.DbValue.GetSqlValue(value, token, column); builder.AppendMember(invoker.Member.Name); builder.Append(" = "); builder.Append(seg); builder.Append(" AND "); } builder.Length -= 5; } else if (dQueryInfo.SelectInfo != null) { LambdaExpression lambda = null; var dbQuery = dQueryInfo.SourceQuery; if (dbQuery.DbExpressions != null && dbQuery.DbExpressions.Count > 1) { switch (dbQuery.DbExpressions[1].DbExpressionType) { case DbExpressionType.Join: case DbExpressionType.GroupJoin: case DbExpressionType.GroupRightJoin: lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[1]; break; case DbExpressionType.Select: case DbExpressionType.SelectMany: lambda = (LambdaExpression)dbQuery.DbExpressions[1].Expressions[0]; break; } } if (lambda == null) { DbExpression dbExpression = dQueryInfo.SelectInfo.SelectExpression; dbExpression = dQueryInfo.SelectInfo.WhereExpression; if (dbExpression != null && dbExpression.Expressions != null) { lambda = (LambdaExpression)dbExpression.Expressions[0]; } } // 解析查询以确定是否需要嵌套 var parameter = Expression.Parameter(typeof(SQLiteRowId), lambda != null ? lambda.Parameters[0].Name : "x"); var expression = Expression.MakeMemberAccess(parameter, (_rowIdExpression.Body as MemberExpression).Member); dQueryInfo.SelectInfo.SelectExpression = new DbExpression(DbExpressionType.Select, expression); var cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, null); if (token != null && token.Extendsions == null) { token.Extendsions = new Dictionary <string, object>(); if (!token.Extendsions.ContainsKey("SQLiteDelete")) { token.Extendsions.Add("SQLiteDelete", null); } } if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dQueryInfo.SelectInfo.Joins.Count > 0) { cmd = (MappingCommand)this.ParseSelectCommand <T>(dQueryInfo.SelectInfo, 1, false, token); builder.Append("WHERE "); builder.AppendMember("RowID"); builder.Append(" IN("); builder.AppendNewLine(cmd.CommandText); builder.Append(')'); } else { TableAliasCache aliases = this.PrepareAlias <T>(dQueryInfo.SelectInfo, token); ExpressionVisitorBase visitor = null; visitor = new JoinExpressionVisitor(this, aliases, dQueryInfo.SelectInfo.Joins); visitor.Write(builder); visitor = new WhereExpressionVisitor(this, null, dQueryInfo.SelectInfo.WhereExpression); visitor.Write(builder); } } builder.Append(';'); return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
// 创建 INSRT 命令 protected override CommandDefine ParseInsertCommand <T>(DbQueryableInfo_Insert <T> qInsert) { SqlBuilder builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight); var rInfo = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); TableAliasCache aliases = new TableAliasCache(); if (qInsert.Entity != null) { object entity = qInsert.Entity; SqlBuilder columns = new SqlBuilder(this.EscCharLeft, this.EscCharRight); SqlBuilder values = new SqlBuilder(this.EscCharLeft, this.EscCharRight); foreach (var kv in rInfo.Wrappers) { var wrapper = kv.Value as MemberAccessWrapper; var column = wrapper.Column; if (column != null && column.NoMapped) { continue; } if (wrapper.ForeignKey != null) { continue; } if (wrapper != qInsert.AutoIncrement) { columns.AppendMember(wrapper.Member.Name); columns.Append(','); var value = wrapper.Get(entity); string seg = ExpressionVisitorBase.GetSqlValue(value); values.Append(seg); values.Append(','); } } columns.Length -= 1; values.Length -= 1; if (qInsert.Bulk == null || !qInsert.Bulk.OnlyValue) { builder.Append("INSERT INTO "); builder.AppendMember(rInfo.TableName); builder.AppendNewLine(); builder.Append('('); builder.Append(columns); builder.Append(')'); builder.AppendNewLine(); builder.Append("VALUES"); builder.AppendNewLine(); } builder.Append('('); builder.Append(values); builder.Append(')'); if (qInsert.Bulk != null && !qInsert.Bulk.IsOver) { builder.Append(","); } if (qInsert.Bulk == null && qInsert.AutoIncrement != null) { builder.AppendNewLine(); builder.Append("SELECT CAST(SCOPE_IDENTITY() AS INT)"); } } else if (qInsert.SelectInfo != null) { builder.Append("INSERT INTO "); builder.AppendMember(rInfo.TableName); builder.Append('('); CommandDefine_Select sc = this.ParseSelectCommand(qInsert.SelectInfo) as CommandDefine_Select; //for (int i = 0; i < seg.Columns.Count; i++) int i = 0; foreach (var kvp in sc.Columns) { builder.AppendMember(kvp.Key); if (i < sc.Columns.Count - 1) { builder.Append(','); builder.AppendNewLine(); } i++; } builder.Append(')'); builder.AppendNewLine(); builder.Append(sc.CommandText); } return(new CommandDefine(builder.ToString(), null, System.Data.CommandType.Text)); //builder.ToString(); }
/// <summary> /// 创建 DELETE 命令 /// </summary> /// <param name="dbQuery">查询语义</param> /// <param name="token">解析上下文</param> /// <returns></returns> protected override RawCommand ResolveDeleteCommand <T>(IDbQueryableInfo_Delete dbQuery, ResolveToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("DELETE FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" "); if (dbQuery.Entity != null) { if (typeRuntime.KeyMembers == null || typeRuntime.KeyMembers.Count == 0) { throw new XFrameworkException("Delete<T>(T value) require entity must have key column."); } object entity = dbQuery.Entity; builder.AppendNewLine(); builder.Append("WHERE "); foreach (var m in typeRuntime.KeyMembers) { var column = m.Column; var value = m.Invoke(entity); var seg = this.DbValue.GetSqlValue(value, token, column); builder.AppendMember(m.Member.Name); builder.Append(" = "); builder.Append(seg); builder.Append(" AND "); } builder.Length -= 5; } else if (dbQuery.Query != null) { // 解析查询用来确定是否需要嵌套 var cmd = this.ResolveSelectCommand(dbQuery.Query, 1, false, null) as MappingCommand; if (token != null && token.Extendsions == null) { token.Extendsions = new Dictionary <string, object>(); if (!token.Extendsions.ContainsKey("SQLiteDelete")) { token.Extendsions.Add("SQLiteDelete", null); } } if ((cmd.NavMembers != null && cmd.NavMembers.Count > 0) || dbQuery.Query.Joins.Count > 0) { // 最外层仅选择 RowID 列 var outQuery = dbQuery.Query; outQuery.Select = new DbExpression(DbExpressionType.Select, Expression.Constant("t0.RowId", typeof(string))); var iterator = outQuery; while (iterator.Subquery != null) { var subQuery = new SQLiteDbQueryableInfo_Select(iterator.Subquery); iterator.Subquery = subQuery; iterator = subQuery; } // 解析成 RowId IN 结构 cmd = (MappingCommand)this.ResolveSelectCommand(dbQuery.Query, 1, false, token); builder.Append("WHERE "); builder.AppendMember("RowID"); builder.Append(" IN("); builder.AppendNewLine(cmd.CommandText); builder.Append(')'); } else { TableAlias aliases = this.PrepareTableAlias(dbQuery.Query, token); ExpressionVisitorBase visitor = null; visitor = new JoinExpressionVisitor(this, aliases, dbQuery.Query.Joins); visitor.Write(builder); visitor = new WhereExpressionVisitor(this, null, dbQuery.Query.Where); visitor.Write(builder); } } builder.Append(';'); return(new RawCommand(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
// 创建 UPDATE 命令 protected override Command ParseUpdateCommand <T>(DbQueryableInfo_Update <T> uQueryInfo, ParserToken token) { ISqlBuilder builder = this.CreateSqlBuilder(token); var typeRuntime = TypeRuntimeInfoCache.GetRuntimeInfo <T>(); builder.Append("UPDATE t0 SET"); builder.AppendNewLine(); if (uQueryInfo.Entity != null) { object entity = uQueryInfo.Entity; ISqlBuilder whereBuilder = this.CreateSqlBuilder(token); bool useKey = false; int length = 0; foreach (var kv in typeRuntime.Invokers) { MemberInvokerBase invoker = kv.Value; var column = invoker.Column; if (column != null && column.IsIdentity) { goto gotoLabel; // fix issue# 自增列同时又是主键 } if (column != null && column.NoMapped) { continue; } if (invoker.Column != null && column.DbType is SqlDbType && (SqlDbType)column.DbType == SqlDbType.Timestamp) { continue; // 行版本号 } if (invoker.ForeignKey != null) { continue; } if (invoker.Member.MemberType == System.Reflection.MemberTypes.Method) { continue; } builder.AppendMember("t0", invoker.Member.Name); builder.Append(" = "); gotoLabel: var value = invoker.Invoke(entity); var seg = builder.GetSqlValueWidthDefault(value, column); if (column == null || !column.IsIdentity) { builder.Append(seg); length = builder.Length; builder.Append(','); builder.AppendNewLine(); } if (column != null && column.IsKey) { useKey = true; whereBuilder.AppendMember("t0", invoker.Member.Name); whereBuilder.Append(" = "); whereBuilder.Append(seg); whereBuilder.Append(" AND "); } } if (!useKey) { throw new XFrameworkException("Update<T>(T value) require T must have key column."); } builder.Length = length; whereBuilder.Length -= 5; builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.Append(" t0"); builder.AppendNewLine(); builder.Append("WHERE "); builder.Append(whereBuilder); } else if (uQueryInfo.Expression != null) { TableAliasCache aliases = this.PrepareAlias <T>(uQueryInfo.SelectInfo, token); ExpressionVisitorBase visitor = null; visitor = new UpdateExpressionVisitor(this, aliases, uQueryInfo.Expression); visitor.Write(builder); builder.AppendNewLine(); builder.Append("FROM "); builder.AppendMember(typeRuntime.TableName, !typeRuntime.IsTemporary); builder.AppendAs("t0"); var cmd2 = new SelectCommand(this, aliases, token) { HasManyNavigation = uQueryInfo.SelectInfo.HasManyNavigation }; visitor = new JoinExpressionVisitor(this, aliases, uQueryInfo.SelectInfo.Joins); visitor.Write(cmd2.JoinFragment); visitor = new WhereExpressionVisitor(this, aliases, uQueryInfo.SelectInfo.WhereExpression); visitor.Write(cmd2.WhereFragment); cmd2.AddNavMembers(visitor.NavMembers); builder.Append(cmd2.CommandText); } return(new Command(builder.ToString(), builder.Token != null ? builder.Token.Parameters : null, System.Data.CommandType.Text)); }
/// <summary> /// 创建方法表达式访问器 /// </summary> /// <param name="visitor">表达式访问器</param> /// <returns></returns> public override MethodCallExpressionVisitor CreateMethodVisitor(ExpressionVisitorBase visitor) { return(new SQLiteMethodCallExressionVisitor(this, visitor)); }
// 创建 SELECT 命令 protected override CommandDefine ParseSelectCommand <T>(DbQueryableInfo_Select <T> qQuery, int indent = 0) { // 说明: // 1.OFFSET 前必须要有 'ORDER BY',即 'Skip' 子句前必须使用 'OrderBy' 子句 // 2.在有统计函数的<MAX,MIN...>情况下,如果有 'Distinct' 'GroupBy' 'Skip' 'Take' 子句,则需要使用嵌套查询 // 3.'Any' 子句将翻译成 IF EXISTS... // 4.分组再分页时需要使用嵌套查询,此时子查询不需要 'OrderBy' 子句,但最外层则需要 // 5.'Skip' 'Take' 子句视为语义结束符,在其之后的子句将使用嵌套查询 bool willNest = qQuery.HaveDistinct || qQuery.GroupBy != null || qQuery.Skip > 0 || qQuery.Take > 0; bool useStatis = qQuery.Statis != null; bool groupByPaging = qQuery.GroupBy != null && qQuery.Skip > 0; // 分组分页 bool useOrderBy = (!useStatis || qQuery.Skip > 0) && !qQuery.HaveAny; // 没有统计函数或者使用 'Skip' 子句,则解析OrderBy ExpressionVisitorBase visitor = null; TableAliasCache aliases = this.PrepareAlias <T>(qQuery); string statName = string.Empty; CommandDefine_Select sc = new CommandDefine_Select(this.EscCharLeft, this.EscCharRight, aliases); SqlBuilder jf = sc.JoinFragment; SqlBuilder wf = sc.WhereFragment; if (groupByPaging) { indent = indent + 1; } jf.Indent = indent; #region 嵌套查询 if (useStatis && willNest) { // SELECT jf.Append("SELECT "); jf.AppendNewLine(); // SELECT COUNT(1) visitor = new StatisExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy, "t0"); visitor.Write(jf); statName = (visitor as StatisExpressionVisitor).ColumnName; sc.AddNavigation(visitor.Navigations); // SELECT COUNT(1) FROM jf.AppendNewLine(); jf.Append("FROM ( "); indent += 1; jf.Indent = indent; } #endregion // SELECT 子句 if (jf.Indent > 0) { jf.AppendNewLine(); } if (qQuery.HaveAny) { jf.Append("IF EXISTS("); indent += 1; jf.Indent = indent; jf.AppendNewLine(); } jf.Append("SELECT "); if (useStatis && !willNest) { // 如果有统计函数,并且不是嵌套的话,则直接使用SELECT <MAX,MIN...>,不需要解析选择的字段 jf.AppendNewLine(); visitor = new StatisExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy); visitor.Write(jf); sc.AddNavigation(visitor.Navigations); } else { // DISTINCT 子句 if (qQuery.HaveDistinct) { jf.Append("DISTINCT "); } // TOP 子句 if (qQuery.Take > 0 && qQuery.Skip == 0) { jf.AppendFormat("TOP({0})", qQuery.Take); } // Any if (qQuery.HaveAny) { jf.Append("TOP 1 1"); } #region 择字段 if (!qQuery.HaveAny) { // SELECT 范围 visitor = new ColumnExpressionVisitor(this, aliases, qQuery.Expression, qQuery.GroupBy); visitor.Write(jf); sc.Columns = (visitor as ColumnExpressionVisitor).Columns; sc.NavDescriptors = (visitor as ColumnExpressionVisitor).NavDescriptors; sc.AddNavigation(visitor.Navigations); // 如果有统计,选择列中还要追加统计的列 if (useStatis && willNest) { string columnName = statName; if (!string.IsNullOrEmpty(columnName) && !sc.Columns.ContainsKey(columnName)) { if (sc.Columns.Count > 0) { jf.Append(","); } visitor = new ColumnExpressionVisitor(this, aliases, qQuery.Statis, qQuery.GroupBy, true); visitor.Write(jf); sc.Columns.Add(columnName, new Column { Name = columnName, Duplicate = 1 }); sc.AddNavigation(visitor.Navigations); } } // 如果分组后再分页,此时需要在原先的选择字段上再加上 'OrderBy' 子句指定的字段,外层的分页时需要用到这些排序字段 if (qQuery.OrderBy.Count > 0 && useOrderBy && groupByPaging) { if (sc.Columns.Count > 0) { jf.Append(","); } for (int i = 0; i < qQuery.OrderBy.Count; i++) { visitor = new ColumnExpressionVisitor(this, aliases, qQuery.OrderBy[i], qQuery.GroupBy, true); visitor.Write(jf); sc.AddNavigation(visitor.Navigations); if (i < qQuery.OrderBy.Count - 1) { jf.AppendNewLine(","); } } } } #endregion } // FROM 子句 jf.AppendNewLine(); jf.Append("FROM "); if (qQuery.Subquery != null) { // 子查询 jf.Append("("); CommandDefine define = this.ParseSelectCommand <T>(qQuery.Subquery as DbQueryableInfo_Select <T>, indent + 1); jf.Append(define.CommandText); jf.AppendNewLine(); jf.Append(")"); } else { jf.AppendMember(TypeRuntimeInfoCache.GetRuntimeInfo(qQuery.FromType).TableName); } jf.Append(" t0 "); if (!string.IsNullOrEmpty(DbQueryProvider.NOLOCK)) { jf.Append(DbQueryProvider.NOLOCK); } // LEFT<INNER> JOIN 子句 visitor = new JoinExpressionVisitor(this, aliases, qQuery.Join); visitor.Write(jf); wf.Indent = jf.Indent; // WHERE 子句 visitor = new WhereExpressionVisitor(this, aliases, qQuery.Where); visitor.Write(wf); sc.AddNavigation(visitor.Navigations); // GROUP BY 子句 visitor = new GroupByExpressionVisitor(this, aliases, qQuery.GroupBy); visitor.Write(wf); sc.AddNavigation(visitor.Navigations); // HAVING 子句 visitor = new HavingExpressionVisitor(this, aliases, qQuery.Having, qQuery.GroupBy); visitor.Write(wf); sc.AddNavigation(visitor.Navigations); // ORDER 子句 if (qQuery.OrderBy.Count > 0 && useOrderBy && !groupByPaging) { visitor = new OrderByExpressionVisitor(this, aliases, qQuery.OrderBy, qQuery.GroupBy); visitor.Write(wf); sc.AddNavigation(visitor.Navigations); } #region 分页查询 if (qQuery.Skip > 0 && !groupByPaging) { if (qQuery.OrderBy.Count == 0) { throw new XfwException("The method 'OrderBy' must be called before the method 'Skip'."); } wf.AppendNewLine(); wf.Append("OFFSET "); wf.Append(qQuery.Skip); wf.Append(" ROWS"); if (qQuery.Take > 0) { wf.Append(" FETCH NEXT "); wf.Append(qQuery.Take); wf.Append(" ROWS ONLY "); } } #endregion #region 嵌套查询 if (useStatis && willNest) { string inner = sc.CommandText; indent -= 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append(" ) t0"); } #endregion #region 分组分页 if (groupByPaging) { SqlBuilder builder = new SqlBuilder(this.EscCharLeft, this.EscCharRight); // SELECT int index = -1; builder.Append("SELECT "); foreach (var kvp in sc.Columns) { index += 1; builder.AppendNewLine(); builder.AppendMember("t0", kvp.Key); if (index < sc.Columns.Count - 1) { builder.Append(","); } } builder.AppendNewLine(); builder.Append("FROM ( "); string inner = sc.CommandText; //jf.Replace(Environment.NewLine, Environment.NewLine + SqlBuilder.TAB); jf.Insert(0, builder); indent -= 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append(" ) t0"); // 排序 if (qQuery.OrderBy.Count > 0 && useOrderBy) { visitor = new OrderByExpressionVisitor(this, aliases, qQuery.OrderBy, null, "t0"); visitor.Write(jf); } // 分页 if (qQuery.Skip > 0) { jf.AppendNewLine(); jf.Append("OFFSET "); jf.Append(qQuery.Skip); jf.Append(" ROWS"); if (qQuery.Take > 0) { jf.Append(" FETCH NEXT "); jf.Append(qQuery.Take); jf.Append(" ROWS ONLY "); } } } #endregion // 'Any' 子句 if (qQuery.HaveAny) { string inner = sc.CommandText; indent -= 1; jf.Indent = indent; jf.AppendNewLine(); jf.Append(") SELECT 1 ELSE SELECT 0"); } // UNION 子句 if (qQuery.Union != null && qQuery.Union.Count > 0) { string inner = sc.CommandText; for (int index = 0; index < qQuery.Union.Count; index++) { jf.AppendNewLine(); jf.AppendNewLine("UNION ALL"); CommandDefine define = this.ParseSelectCommand <T>(qQuery.Union[index] as DbQueryableInfo_Select <T>); jf.Append(define.CommandText); } } return(sc); }
public static DbExpression VisitFilterPredicate(LambdaExpression lambda, List <IMappingObjectExpression> moeList) { return(GeneralExpressionVisitor.VisitPredicate(ExpressionVisitorBase.ReBuildFilterPredicate(lambda), moeList)); }
public static DbExpression ParseFilterPredicate(LambdaExpression lambda, ScopeParameterDictionary scopeParameters, KeyDictionary <string> scopeTables) { return(GeneralExpressionVisitor.ParseLambda(ExpressionVisitorBase.ReBuildFilterPredicate(lambda), scopeParameters, scopeTables)); }