Exemplo n.º 1
0
        protected override Expression VisitMethodCall(MethodCallExpression methodExp)
        {
            switch (methodExp.Method.Name)
            {
            case "Contains":
                if (methodExp.Method.DeclaringType == typeof(string))
                {
                    this.Visit(methodExp.Object);
                    SqlBuilder.AppendFormat(SqlDialect.Contains(), TranslateClause(methodExp.Arguments[0]));
                    return(methodExp);
                }
                else
                {
                    Expression mex;
                    if (methodExp.Object != null)
                    {
                        this.Visit(methodExp.Arguments[0]);
                        SqlBuilder.Append(" IN (");
                        mex = methodExp.Object;
                    }
                    else
                    {
                        this.Visit(methodExp.Arguments[1]);
                        SqlBuilder.Append(" IN (");
                        mex = methodExp.Arguments[0];
                    }
                    if (mex.NodeType == ExpressionType.Call && mex is MethodCallExpression && ((MethodCallExpression)mex).Method.DeclaringType == typeof(SubQuery))
                    {
                        this.Visit(mex);
                    }
                    else
                    {
                        IEnumerable result = Expression.Lambda(mex).Compile().DynamicInvoke() as IEnumerable;
                        int         length = 0;
                        foreach (var v in result)
                        {
                            length++;
                            this.Visit(Expression.Constant(v));
                            SqlBuilder.Append(",");
                        }
                        if (length == 0)
                        {
                            SqlBuilder.Append("NULL,");
                        }
                        SqlBuilder.Remove(SqlBuilder.Length - 1, 1);
                    }
                    SqlBuilder.Append(")");
                    return(methodExp);
                }

            case "ToUpper":
                SqlBuilder.Append(" UPPER(");
                this.Visit(methodExp.Object);
                SqlBuilder.Append(")");
                return(methodExp);

            case "ToLower":
                SqlBuilder.Append(" LOWER(");
                this.Visit(methodExp.Object);
                SqlBuilder.Append(")");
                return(methodExp);

            case "CompareTo":
                IsPreTreatBinary = true;
                this.Visit(methodExp.Object);
                SqlBuilder.Append("{0}");
                this.Visit(methodExp.Arguments[0]);
                return(methodExp);

            case "Equals":
                this.Visit(methodExp.Object);
                SqlBuilder.Append("=");
                this.Visit(methodExp.Arguments[0]);
                return(methodExp);

            case "IndexOf":
                SqlBuilder.AppendFormat(SqlDialect.IndexOf(), TranslateClause(methodExp.Arguments[0]), TranslateClause(methodExp.Object));
                return(methodExp);

            case "IsNullOrEmpty":
                string   template = " ({0} IS NULL OR {0}='') ";
                string[] sections = template.Split(new string[] { "{0}" }, StringSplitOptions.None);
                for (int i = 0; i < sections.Length - 1; i++)
                {
                    if (i == 0)
                    {
                        SqlBuilder.Append(sections[i]);
                    }
                    this.Visit(methodExp.Arguments[0]);
                    SqlBuilder.Append(sections[i + 1]);
                }
                return(methodExp);

            case "ToString":
                //Convert.ToString()
                if (methodExp.Method.DeclaringType == typeof(System.Convert))
                {
                    MemberTypeVisitor mtVisitor = new MemberTypeVisitor();
                    MemberType = mtVisitor.Translate(methodExp.Arguments[0]);
                    if (MemberType != null)
                    {
                        SqlBuilder.AppendFormat(SqlDialect.ToChar(), TranslateClause(methodExp.Arguments[0]));
                        return(methodExp);
                    }
                }
                else if (methodExp.Method.DeclaringType == typeof(System.Object))
                {
                    MemberTypeVisitor mtVisitor = new MemberTypeVisitor();
                    MemberType = mtVisitor.Translate(methodExp.Object);
                    if (MemberType != null)
                    {
                        SqlBuilder.AppendFormat(SqlDialect.ToChar(), TranslateClause(methodExp.Object));
                        return(methodExp);
                    }
                }
                else if (methodExp.Method.DeclaringType == typeof(Nullable <DateTime>) || methodExp.Method.DeclaringType == typeof(DateTime))
                {
                    if (methodExp.Arguments[0] is ConstantExpression)
                    {
                        MemberTypeVisitor mtVisitor = new MemberTypeVisitor();
                        MemberType = mtVisitor.Translate(methodExp.Object);
                        if (MemberType != null)
                        {
                            string timeFormat = ((ConstantExpression)methodExp.Arguments[0]).Value as string;
                            string clause     = TranslateClause(methodExp.Object);
                            //非列就转向了
                            if (string.IsNullOrEmpty(clause))
                            {
                                goto default;
                            }
                            SqlBuilder.AppendFormat("(" + SqlDialect.ParseTimeFormat(timeFormat) + ")", clause);
                            return(methodExp);
                        }
                    }
                }
                goto default;

            case "ToInt32":
                //Convert.ToInt32()
                if (methodExp.Method.DeclaringType == typeof(System.Convert))
                {
                    MemberTypeVisitor mtVisitor = new MemberTypeVisitor();
                    MemberType = mtVisitor.Translate(methodExp.Arguments[0]);
                    if (MemberType != null)
                    {
                        SqlBuilder.AppendFormat(SqlDialect.ToNumber(), TranslateClause(methodExp.Arguments[0]));
                        return(methodExp);
                    }
                }
                goto default;

            case "ToDateTime":
                if (methodExp.Method.DeclaringType == typeof(System.Convert))
                {
                    MemberTypeVisitor mtVisitor = new MemberTypeVisitor();
                    MemberType = mtVisitor.Translate(methodExp.Arguments[0]);
                    if (MemberType == typeof(Nullable <DateTime>) || MemberType == typeof(DateTime))
                    {
                        this.Visit(methodExp.Arguments[0]);
                        return(methodExp);
                    }
                    else if (MemberType == typeof(string))
                    {
                        SqlBuilder.AppendFormat(SqlDialect.ToDateTime(), TranslateClause(methodExp.Arguments[0]));
                        return(methodExp);
                    }
                }
                goto default;

            case "StartsWith":
                this.Visit(methodExp.Object);
                SqlBuilder.AppendFormat(SqlDialect.StartsWith(), TranslateClause(methodExp.Arguments[0]));
                return(methodExp);

            case "EndsWith":
                this.Visit(methodExp.Object);
                SqlBuilder.AppendFormat(SqlDialect.EndsWith(), TranslateClause(methodExp.Arguments[0]));
                return(methodExp);

            case "TrimStart":
                SqlBuilder.Append(" LTRIM(");
                this.Visit(methodExp.Object);
                SqlBuilder.Append(")");
                return(methodExp);

            case "TrimEnd":
                SqlBuilder.Append(" RTRIM(");
                this.Visit(methodExp.Object);
                SqlBuilder.Append(")");
                return(methodExp);

            case "Trim":
                SqlBuilder.Append(" RTRIM(LTRIM(");
                this.Visit(methodExp.Object);
                SqlBuilder.Append("))");
                return(methodExp);

            case "Count":
                if (methodExp.Method.DeclaringType == typeof(SqlFunctions))
                {
                    SqlBuilder.AppendFormat("COUNT({0})", TranslateClause(methodExp.Arguments[0]));
                    return(methodExp);
                }
                goto default;

            case "CountDistinct":
                if (methodExp.Method.DeclaringType == typeof(SqlFunctions))
                {
                    SqlBuilder.AppendFormat("COUNT(DISTINCT {0})", TranslateClause(methodExp.Arguments[0]));
                    return(methodExp);
                }
                goto default;

            case "Max":
            case "Min":
            case "Avg":
                if (methodExp.Method.DeclaringType == typeof(SqlFunctions))
                {
                    SqlBuilder.AppendFormat("{0}({1})", methodExp.Method.Name, TranslateClause(methodExp.Arguments[0]));
                    return(methodExp);
                }
                goto default;

            case "GetSingle":
                if (methodExp.Method.DeclaringType == typeof(SubQuery))
                {
                    Expression opd1 = methodExp.Arguments[0];
                    Expression opd2 = methodExp.Arguments[1];
                    if (methodExp.Arguments[0].NodeType == ExpressionType.Quote)
                    {
                        opd1 = ((UnaryExpression)(methodExp.Arguments[0])).Operand;
                    }
                    if (methodExp.Arguments[1].NodeType == ExpressionType.Quote)
                    {
                        opd2 = ((UnaryExpression)(methodExp.Arguments[1])).Operand;
                    }
                    if (WithAlias)
                    {
                        SqlBuilder.AppendFormat("(SELECT {0} FROM {1} AS {3} WHERE {2})", TranslateClause(((LambdaExpression)opd2).Body), GetTableName(((LambdaExpression)opd1).Parameters[0].Type), TranslateClause(((LambdaExpression)opd1).Body), ((LambdaExpression)opd1).Parameters[0].Name);
                    }
                    else
                    {
                        SqlBuilder.AppendFormat("(SELECT {0} FROM {1} WHERE {2})", TranslateClause(((LambdaExpression)opd2).Body), GetTableName(((LambdaExpression)opd1).Parameters[0].Type), TranslateClause(((LambdaExpression)opd1).Body));
                    }
                    return(methodExp);
                }
                goto default;

            case "GetList":
                if (methodExp.Method.DeclaringType == typeof(SubQuery))
                {
                    Expression opd1 = methodExp.Arguments[0];
                    Expression opd2 = methodExp.Arguments[1];
                    if (methodExp.Arguments[0].NodeType == ExpressionType.Quote)
                    {
                        opd1 = ((UnaryExpression)(methodExp.Arguments[0])).Operand;
                    }
                    if (methodExp.Arguments[1].NodeType == ExpressionType.Quote)
                    {
                        opd2 = ((UnaryExpression)(methodExp.Arguments[1])).Operand;
                    }
                    if (WithAlias)
                    {
                        SqlBuilder.AppendFormat("SELECT {0} FROM {1} AS {3} WHERE {2}", TranslateClause(((LambdaExpression)opd2).Body), GetTableName(((LambdaExpression)opd1).Parameters[0].Type), TranslateClause(((LambdaExpression)opd1).Body), ((LambdaExpression)opd1).Parameters[0].Name);
                    }
                    else
                    {
                        SqlBuilder.AppendFormat("SELECT {0} FROM {1} WHERE {2}", TranslateClause(((LambdaExpression)opd2).Body), GetTableName(((LambdaExpression)opd1).Parameters[0].Type), TranslateClause(((LambdaExpression)opd1).Body));
                    }
                    return(methodExp);
                }
                goto default;

            default:
                try
                {
                    object result = Expression.Lambda(methodExp).Compile().DynamicInvoke();
                    var    r      = Expression.Constant(result, methodExp.Method.ReturnType);
                    this.Visit(r);
                    return(r);
                }
                catch
                {
                    if (methodExp.Object != null)
                    {
                        Expression obj = this.Visit(methodExp.Object);
                        return(obj);
                    }
                    else
                    {
                        Expression obj = this.Visit(methodExp.Arguments[0]);
                        return(obj);
                    }
                }
                throw new NotSupportedException(string.Format("lambda表达式不支持使用此'{0}'方法,请自行扩展", methodExp.Method.Name));
            }
        }