/// <summary> /// 处理where条件表达式,如果表达式为空,默认使用Id /// </summary> /// <typeparam name="TType"></typeparam> /// <param name="visitor"></param> /// <param name="where"></param> private static string VisitWhereExpress <TType>(SqlExpressionVisitor visitor, Expression <Func <TType, bool> > where) { if (where != null) { var whereFlag = new SqlVistorFlag(SqlVistorType.Where); visitor.Visit(@where, whereFlag); return(string.Concat(" WHERE ", whereFlag.Sql)); } const string sql = " WHERE Id=@Id"; if (visitor.Properties.ContainsKey("id")) { return(sql); } var p = typeof(TType).GetProperty("id"); if (p == null) { throw new Exception("Update操作中where条件为空,且未发现Id属性"); } visitor.Properties.Add("id", p); return(sql); }
protected virtual void VisitUnary(UnaryExpression u, SqlVistorFlag flag) { var nodeType = flag.UnaryType; flag.UnaryType = u.NodeType; Visit(u.Operand, flag); flag.UnaryType = nodeType; }
private void MethodCallLike(MethodCallExpression exp, SqlVistorFlag flag) { Visit(exp.Object, flag); flag.Append(GetUnaryOperater(flag.UnaryType)); flag.Append(" LIKE CONCAT('%',"); VisitRight(exp.Arguments[0], flag); flag.Append(",'%')"); }
/// <summary> /// 递归解析时,保留上层的IsRight状态 /// </summary> /// <param name="exp"></param> /// <param name="flag"></param> protected virtual void VisitRight(Expression exp, SqlVistorFlag flag) { var isRight = flag.IsRight; flag.IsRight = true; Visit(exp, flag); flag.IsRight = isRight; // 回归 }
/// <summary> /// 递归解析时,保留上层的IsRight状态 /// </summary> /// <param name="exp"></param> /// <param name="flag"></param> private void VisitRight(Expression exp, SqlVistorFlag flag) { var isRight = flag.IsRight; flag.IsRight = true; Visit(exp, flag); flag.IsRight = isRight; // 回归 }
protected virtual void VisitNew(NewExpression nex, SqlVistorFlag flag) { for (var i = 0; i < nex.Members.Count; i++) { var arg = nex.Arguments[i]; var member = nex.Members[i]; flag.Append(flag.GetColName(member.Name)).Append("="); VisitRight(arg, flag); } }
protected virtual void VisitNew(NewExpression nex, SqlVistorFlag flag) { for (var i = 0; i < nex.Members.Count; i++) { var arg = nex.Arguments[i]; var member = nex.Members[i]; flag.Append(string.Concat("`", member.Name, "`", "="), true); VisitRight(arg, flag); } }
private static void GetUpdateExpressionSql <TType>(Expression <Func <TType, object> > update, Expression <Func <TType, bool> > where, string tableName, SqlExpressionVisitor visitor, StringBuilder sql) { sql.Append("UPDATE ").Append(tableName).Append(" SET "); var updateFlag = new SqlVistorFlag(SqlVistorType.Update); visitor.Visit(update, updateFlag); sql.Append(updateFlag.Sql); sql.Append(" ").Append(VisitWhereExpress(visitor, where)); }
protected virtual void VisitMember(MemberExpression exp, SqlVistorFlag flag) { if (flag.IsRight) { var proParaName = GetParaName(exp.Member.Name); flag.Append(proParaName); AddMemberProperty(proParaName, exp.Member.DeclaringType.GetProperty(exp.Member.Name)); } else { flag.Append(exp.Member.Name); } }
protected virtual void VisitMethodCall(MethodCallExpression exp, SqlVistorFlag flag) { var methodName = exp.Method.Name; switch (methodName) //这里其实还可以改成反射调用,不用写switch { case "Contains": MethodCallLike(exp, flag); break; // todo 补充其他方法 } }
protected virtual void VisitConstant(ConstantExpression c, SqlVistorFlag flag) { var value = c.Value ?? "null"; if (flag.IsRight) { var paraName = flag.GetCustomParaName(); flag.Append(paraName); AddParameter(paraName, c.Type == typeof(bool) ? ((bool)value ? 1 : 0) : value); } else { flag.Append(value.ToString()); } }
protected virtual void VisitConstant(ConstantExpression c, SqlVistorFlag flag) { var value = c.Value ?? "null"; if (flag.IsRight) { const string parameterPre = "ConstPara"; var paraName = GetParaName(parameterPre, true); flag.Append(paraName); AddParameter(paraName, value); } else { flag.Append(value.ToString()); } }
protected virtual void VisitMember(MemberExpression exp, SqlVistorFlag flag) { if (exp.Expression != null && exp.Expression.NodeType == ExpressionType.Parameter) { if (flag.IsRight) { var proParaName = flag.GetParaName(exp.Member.Name); flag.Append(proParaName); AddMemberProperty(proParaName, exp.Member.DeclaringType.GetProperty(exp.Member.Name)); } else { if (exp.Member.DeclaringType.GetTypeInfo().IsGenericType && exp.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (exp.Member.Name == "Value") { Visit(exp.Expression, flag); } if (exp.Member.Name != "HasValue") { return; } var doesNotEqualNull = Expression.MakeBinary(ExpressionType.NotEqual, exp.Expression, Expression.Constant(null)); Visit(doesNotEqualNull, flag); } else { flag.Append(flag.GetColName(exp.Member.Name)); } } } else if (exp.Expression != null && flag.IsRight) { var value = Expression.Lambda(exp).Compile().DynamicInvoke(); Visit(Expression.Constant(value), flag); } }
protected virtual void VisitBinary(BinaryExpression exp, SqlVistorFlag flag) { var operand = GetBinaryOperater(exp.NodeType); if (exp.NodeType == ExpressionType.AndAlso || exp.NodeType == ExpressionType.OrElse) { flag.Append("("); Visit(exp.Left, flag); flag.Append(") ").Append(operand).Append(" ("); Visit(exp.Right, flag); flag.Append(")"); } else { Visit(exp.Left, flag); flag.Append(operand); VisitRight(exp.Right, flag); } }
protected void VisitNewArray(NewArrayExpression na, SqlVistorFlag flag) { var original = na.Expressions; for (int i = 0, n = original.Count; i < n; i++) { var e = original[i]; if (e.NodeType == ExpressionType.NewArrayInit || e.NodeType == ExpressionType.NewArrayBounds) { var newArrayExpression = e as NewArrayExpression; if (newArrayExpression != null) { VisitNewArray(newArrayExpression, flag); } } else { Visit(e, flag); } } }
protected virtual void VisitMember(MemberExpression exp, SqlVistorFlag flag) { if (exp.Expression != null && exp.Expression.NodeType == ExpressionType.Parameter) { if (flag.IsRight) { var proParaName = GetParaName(exp.Member.Name); flag.Append(proParaName); AddMemberProperty(proParaName, exp.Member.DeclaringType.GetProperty(exp.Member.Name)); } else { if (exp.Member.DeclaringType.GetTypeInfo().IsGenericType && exp.Member.DeclaringType.GetGenericTypeDefinition() == typeof(Nullable <>)) { if (exp.Member.Name == "Value") //Can't use C# 6 yet: nameof(Nullable<bool>.Value) { Visit(exp.Expression, flag); } if (exp.Member.Name == "HasValue") //nameof(Nullable<bool>.HasValue) { var doesNotEqualNull = Expression.MakeBinary(ExpressionType.NotEqual, exp.Expression, Expression.Constant(null)); Visit(doesNotEqualNull, flag); // Nullable<T>.HasValue is equivalent to "!= null" } } else { flag.Append(string.Concat("`", exp.Member.Name, "`"), true); } } } else if (exp.Expression != null && flag.IsRight) { var value = Expression.Lambda(exp).Compile().DynamicInvoke(); Visit(Expression.Constant(value), flag); } }
/// <summary> /// 递归解析方法入口 /// </summary> /// <param name="exp"></param> /// <param name="flag"></param> public virtual void Visit(Expression exp, SqlVistorFlag flag) { switch (exp.NodeType) { case ExpressionType.Lambda: VisitLambda(exp as LambdaExpression, flag); break; case ExpressionType.MemberAccess: VisitMember(exp as MemberExpression, flag); break; case ExpressionType.Add: case ExpressionType.AddChecked: case ExpressionType.Subtract: case ExpressionType.SubtractChecked: case ExpressionType.Multiply: case ExpressionType.MultiplyChecked: case ExpressionType.Divide: case ExpressionType.Modulo: case ExpressionType.And: case ExpressionType.AndAlso: case ExpressionType.Or: case ExpressionType.OrElse: case ExpressionType.LessThan: case ExpressionType.LessThanOrEqual: case ExpressionType.GreaterThan: case ExpressionType.GreaterThanOrEqual: case ExpressionType.Equal: case ExpressionType.NotEqual: case ExpressionType.Coalesce: case ExpressionType.ArrayIndex: case ExpressionType.RightShift: case ExpressionType.LeftShift: case ExpressionType.ExclusiveOr: VisitBinary(exp as BinaryExpression, flag); break; case ExpressionType.Negate: case ExpressionType.NegateChecked: case ExpressionType.Not: case ExpressionType.Convert: case ExpressionType.ConvertChecked: case ExpressionType.ArrayLength: case ExpressionType.Quote: case ExpressionType.TypeAs: VisitUnary(exp as UnaryExpression, flag); break; case ExpressionType.Constant: VisitConstant(exp as ConstantExpression, flag); break; case ExpressionType.Parameter: VisitParameter(exp as ParameterExpression, flag); break; case ExpressionType.Call: VisitMethodCall(exp as MethodCallExpression, flag); break; case ExpressionType.New: VisitNew(exp as NewExpression, flag); break; case ExpressionType.NewArrayInit: case ExpressionType.NewArrayBounds: VisitNewArray(exp as NewArrayExpression, flag); break; case ExpressionType.MemberInit: VisitMemberInit(exp as MemberInitExpression, flag); break; case ExpressionType.Conditional: VisitConditional(exp as ConditionalExpression); break; } }
protected virtual void VisitParameter(ParameterExpression parameterExpression, SqlVistorFlag flag) { // todo }
protected virtual void VisitMemberInit(MemberInitExpression memberInitExpression, SqlVistorFlag flag) { // todo }
protected virtual void VisitLambda(LambdaExpression lambda, SqlVistorFlag flag) { Visit(lambda.Body, flag); }
protected virtual void VisitUnary(UnaryExpression u, SqlVistorFlag flag) { Visit(u.Operand, flag); }