Example #1
0
        public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc)
        {
            if (exp.Expression == null)
            {
                switch (exp.Member.Name)
                {
                case "Zero": return("0");

                case "MinValue": return("-922337203685.477580");    //秒 Ticks / 1000,000,0

                case "MaxValue": return("922337203685.477580");
                }
                return(null);
            }
            var left = ExpressionLambdaToSql(exp.Expression, tsc);

            switch (exp.Member.Name)
            {
            case "Days": return($"floor(({left})/{60 * 60 * 24})");

            case "Hours": return($"mod(({left})/{60 * 60},24)");

            case "Milliseconds": return($"(cast({left} as bigint)*1000)");

            case "Minutes": return($"mod(({left})/60,60)");

            case "Seconds": return($"mod({left},60)");

            case "Ticks": return($"(cast({left} as bigint)*10000000)");

            case "TotalDays": return($"(({left})/{60 * 60 * 24})");

            case "TotalHours": return($"(({left})/{60 * 60})");

            case "TotalMilliseconds": return($"(cast({left} as bigint)*1000)");

            case "TotalMinutes": return($"(({left})/60)");

            case "TotalSeconds": return($"({left})");
            }
            return(null);
        }
Example #2
0
        public override string ExpressionLambdaToSqlMemberAccessString(MemberExpression exp, ExpTSC tsc)
        {
            if (exp.Expression == null)
            {
                switch (exp.Member.Name)
                {
                case "Empty": return("''");
                }
                return(null);
            }
            var left = ExpressionLambdaToSql(exp.Expression, tsc);

            switch (exp.Member.Name)
            {
            case "Length": return($"char_length({left})");
            }
            return(null);
        }
Example #3
0
        public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc)
        {
            if (exp.Expression == null)
            {
                switch (exp.Member.Name)
                {
                case "Now": return(_common.Now);

                case "UtcNow": return(_common.NowUtc);

                case "Today": return("current_date");

                case "MinValue": return("timestamp '0001/1/1 0:00:00'");

                case "MaxValue": return("timestamp'9999/12/31 23:59:59'");
                }
                return(null);
            }
            var left = ExpressionLambdaToSql(exp.Expression, tsc);

            switch (exp.Member.Name)
            {
            case "Date": return($"cast(extract(year from {left}) || '-' || extract(month from {left}) || '-' || extract(day from {left}) as timestamp)");

            case "TimeOfDay": return($"datediff(second from cast(extract(year from {left}) || '-' || extract(month from {left}) || '-' || extract(day from {left}) as timestamp) to {left})");

            case "DayOfWeek": return($"extract(weekday from {left})");

            case "Day": return($"extract(day from {left})");

            case "DayOfYear": return($"datediff(day from {left} to cast(extract(year from {left}) || '-' || extract(month from {left}) || '-' || extract(day from {left}) as timestamp))");

            case "Month": return($"extract(month from {left})");

            case "Year": return($"extract(year from {left})");

            case "Hour": return($"extract(hour from {left})");

            case "Minute": return($"extract(minute from {left})");

            case "Second": return($"extract(second from {left})");

            case "Millisecond": return($"extract(millisecond from {left})");

            case "Ticks": return($"(extract(second from {left})*10000000+621355968000000000)");
            }
            return(null);
        }
Example #4
0
        public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
        {
            Func <Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);

            switch (exp.NodeType)
            {
            case ExpressionType.ArrayLength:
                var arrOper = (exp as UnaryExpression)?.Operand;
                if (arrOper.Type == typeof(byte[]))
                {
                    return($"octet_length({getExp(arrOper)})");
                }
                break;

            case ExpressionType.Convert:
                var operandExp = (exp as UnaryExpression)?.Operand;
                var gentype    = exp.Type.NullableTypeOrThis();
                if (gentype != operandExp.Type.NullableTypeOrThis())
                {
                    switch (gentype.ToString())
                    {
                    case "System.Boolean": return($"({getExp(operandExp)} not in ('0','false'))");

                    case "System.Byte": return($"cast({getExp(operandExp)} as smallint)");

                    case "System.Char": return($"substring(cast({getExp(operandExp)} as varchar(10)) from 1 for 1)");

                    case "System.DateTime": return(ExpressionConstDateTime(operandExp) ?? $"cast({getExp(operandExp)} as timestamp)");

                    case "System.Decimal": return($"cast({getExp(operandExp)} as decimal(18,6))");

                    case "System.Double": return($"cast({getExp(operandExp)} as decimal(18,10))");

                    case "System.Int16": return($"cast({getExp(operandExp)} as smallint)");

                    case "System.Int32": return($"cast({getExp(operandExp)} as integer)");

                    case "System.Int64": return($"cast({getExp(operandExp)} as bigint)");

                    case "System.SByte": return($"cast({getExp(operandExp)} as smallint)");

                    case "System.Single": return($"cast({getExp(operandExp)} as decimal(14,7))");

                    case "System.String": return($"cast({getExp(operandExp)} as blob sub_type 1)");

                    case "System.UInt16": return($"cast({getExp(operandExp)} as integer)");

                    case "System.UInt32": return($"cast({getExp(operandExp)} as bigint)");

                    case "System.UInt64": return($"cast({getExp(operandExp)} as decimal(21,0))");

                    case "System.Guid": return($"substring(cast({getExp(operandExp)} as char(36)) from 1 for 36)");
                    }
                }
                break;

            case ExpressionType.Call:
                var callExp = exp as MethodCallExpression;

                switch (callExp.Method.Name)
                {
                case "Parse":
                case "TryParse":
                    switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString())
                    {
                    case "System.Boolean": return($"({getExp(callExp.Arguments[0])} not in ('0','false'))");

                    case "System.Byte": return($"cast({getExp(callExp.Arguments[0])} as smallint)");

                    case "System.Char": return($"substring(cast({getExp(callExp.Arguments[0])} as varchar(10)) from 1 for 1)");

                    case "System.DateTime": return(ExpressionConstDateTime(callExp.Arguments[0]) ?? $"cast({getExp(callExp.Arguments[0])} as timestamp)");

                    case "System.Decimal": return($"cast({getExp(callExp.Arguments[0])} as decimal(18,6))");

                    case "System.Double": return($"cast({getExp(callExp.Arguments[0])} as decimal(18,10))");

                    case "System.Int16": return($"cast({getExp(callExp.Arguments[0])} as smallint)");

                    case "System.Int32": return($"cast({getExp(callExp.Arguments[0])} as integer)");

                    case "System.Int64": return($"cast({getExp(callExp.Arguments[0])} as bigint)");

                    case "System.SByte": return($"cast({getExp(callExp.Arguments[0])} as smallint)");

                    case "System.Single": return($"cast({getExp(callExp.Arguments[0])} as decimal(14,7))");

                    case "System.String": return($"cast({getExp(callExp.Arguments[0])} as blob sub_type 1)");

                    case "System.UInt16": return($"cast({getExp(callExp.Arguments[0])} as integer)");

                    case "System.UInt32": return($"cast({getExp(callExp.Arguments[0])} as bigint)");

                    case "System.UInt64": return($"cast({getExp(callExp.Arguments[0])} as decimal(18,0))");

                    case "System.Guid": return($"substring(cast({getExp(callExp.Arguments[0])} as char(36)) from 1 for 36)");
                    }
                    return(null);

                case "NewGuid":
                    return(null);

                case "Next":
                    if (callExp.Object?.Type == typeof(Random))
                    {
                        return("cast(rand()*1000000000 as integer)");
                    }
                    return(null);

                case "NextDouble":
                    if (callExp.Object?.Type == typeof(Random))
                    {
                        return("rand()");
                    }
                    return(null);

                case "Random":
                    if (callExp.Method.DeclaringType.IsNumberType())
                    {
                        return("rand()");
                    }
                    return(null);

                case "ToString":
                    if (callExp.Object != null)
                    {
                        return(callExp.Arguments.Count == 0 ? $"cast({getExp(callExp.Object)} as blob sub_type 1)" : null);
                    }
                    return(null);
                }

                var objExp  = callExp.Object;
                var objType = objExp?.Type;
                if (objType?.FullName == "System.Byte[]")
                {
                    return(null);
                }

                var argIndex = 0;
                if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable))
                {
                    objExp  = callExp.Arguments.FirstOrDefault();
                    objType = objExp?.Type;
                    argIndex++;
                }
                if (objType == null)
                {
                    objType = callExp.Method.DeclaringType;
                }
                if (objType != null || objType.IsArrayOrList())
                {
                    if (argIndex >= callExp.Arguments.Count)
                    {
                        break;
                    }
                    tsc.SetMapColumnTmp(null);
                    var args1       = getExp(callExp.Arguments[argIndex]);
                    var oldMapType  = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp);
                    var oldDbParams = objExp?.NodeType == ExpressionType.MemberAccess ? tsc.SetDbParamsReturnOld(null) : null;     //#900 UseGenerateCommandParameterWithLambda(true) 子查询 bug、以及 #1173 参数化 bug
                    tsc.isNotSetMapColumnTmp = true;
                    var left = objExp == null ? null : getExp(objExp);
                    tsc.isNotSetMapColumnTmp = false;
                    tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType);
                    if (oldDbParams != null)
                    {
                        tsc.SetDbParamsReturnOld(oldDbParams);
                    }
                    switch (callExp.Method.Name)
                    {
                    case "Contains":
                        //判断 in //在各大 Provider AdoProvider 中已约定,500元素分割, 3空格\r\n4空格
                        return($"(({args1}) in {left.Replace(",   \r\n    \r\n", $") \r\n OR ({args1}) in (")})");
                    }
                }
                break;

            case ExpressionType.NewArrayInit:
                var arrExp = exp as NewArrayExpression;
                var arrSb  = new StringBuilder();
                arrSb.Append("(");
                for (var a = 0; a < arrExp.Expressions.Count; a++)
                {
                    if (a > 0)
                    {
                        arrSb.Append(",");
                    }
                    if (a % 500 == 499)
                    {
                        arrSb.Append("   \r\n    \r\n");                     //500元素分割, 3空格\r\n4空格
                    }
                    arrSb.Append(getExp(arrExp.Expressions[a]));
                }
                if (arrSb.Length == 1)
                {
                    arrSb.Append("NULL");
                }
                return(arrSb.Append(")").ToString());

            case ExpressionType.ListInit:
                var listExp = exp as ListInitExpression;
                var listSb  = new StringBuilder();
                listSb.Append("(");
                for (var a = 0; a < listExp.Initializers.Count; a++)
                {
                    if (listExp.Initializers[a].Arguments.Any() == false)
                    {
                        continue;
                    }
                    if (a > 0)
                    {
                        listSb.Append(",");
                    }
                    listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
                }
                if (listSb.Length == 1)
                {
                    listSb.Append("NULL");
                }
                return(listSb.Append(")").ToString());

            case ExpressionType.New:
                var newExp = exp as NewExpression;
                if (typeof(IList).IsAssignableFrom(newExp.Type))
                {
                    if (newExp.Arguments.Count == 0)
                    {
                        return("(NULL)");
                    }
                    if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false)
                    {
                        return("(NULL)");
                    }
                    return(getExp(newExp.Arguments[0]));
                }
                return(null);
            }
            return(null);
        }
        public override string ExpressionLambdaToSqlCallString(MethodCallExpression exp, ExpTSC tsc)
        {
            Func <Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);

            if (exp.Object == null)
            {
                switch (exp.Method.Name)
                {
                case "IsNullOrEmpty":
                    var arg1 = getExp(exp.Arguments[0]);
                    return($"({arg1} is null or {arg1} = '')");

                case "IsNullOrWhiteSpace":
                    var arg2 = getExp(exp.Arguments[0]);
                    return($"({arg2} is null or {arg2} = '' or ltrim({arg2}) = '')");

                case "Concat":
                    return(_common.StringConcat(exp.Arguments.Select(a => getExp(a)).ToArray(), null));

                case "Format":
                    if (exp.Arguments[0].NodeType != ExpressionType.Constant)
                    {
                        throw new Exception($"未实现函数表达式 {exp} 解析,参数 {exp.Arguments[0]} 必须为常量");
                    }
                    var expArgsHack = exp.Arguments.Count == 2 && exp.Arguments[1].NodeType == ExpressionType.NewArrayInit ?
                                      (exp.Arguments[1] as NewArrayExpression).Expressions : exp.Arguments.Where((a, z) => z > 0);
                    //3个 {} 时,Arguments 解析出来是分开的
                    //4个 {} 时,Arguments[1] 只能解析这个出来,然后里面是 NewArray []
                    var expArgs = expArgsHack.Select(a => $"'||{_common.IsNull(ExpressionLambdaToSql(a, tsc), "''")}||'").ToArray();
                    return(string.Format(ExpressionLambdaToSql(exp.Arguments[0], tsc), expArgs));

                case "Join":
                    if (exp.IsStringJoin(out var tolistObjectExp, out var toListMethod, out var toListArgs1))
                    {
                        var newToListArgs0 = Expression.Call(tolistObjectExp, toListMethod,
                                                             Expression.Lambda(
                                                                 Expression.Call(
                                                                     typeof(SqlExtExtensions).GetMethod("StringJoinOracleGroupConcat"),
                                                                     Expression.Convert(toListArgs1.Body, typeof(object)),
                                                                     Expression.Convert(exp.Arguments[0], typeof(object))),
                                                                 toListArgs1.Parameters));
                        var newToListSql = getExp(newToListArgs0);
                        return(newToListSql);
                    }
                    break;
                }
            }
            else
            {
                var left = getExp(exp.Object);
                switch (exp.Method.Name)
                {
                case "StartsWith":
                case "EndsWith":
                case "Contains":
                    var args0Value = getExp(exp.Arguments[0]);
                    if (args0Value == "NULL")
                    {
                        return($"({left}) IS NULL");
                    }
                    if (exp.Method.Name == "StartsWith")
                    {
                        return($"({left}) LIKE {(args0Value.EndsWith("'") ? args0Value.Insert(args0Value.Length - 1, "%") : $"(to_char({args0Value})||'%')")}");
                    }
                    if (exp.Method.Name == "EndsWith")
                    {
                        return($"({left}) LIKE {(args0Value.StartsWith("'") ? args0Value.Insert(1, "%") : $"('%'||to_char({args0Value}))")}");
                    }
                    if (args0Value.StartsWith("'") && args0Value.EndsWith("'"))
                    {
                        return($"({left}) LIKE {args0Value.Insert(1, "%").Insert(args0Value.Length, "%")}");
                    }
                    return($"({left}) LIKE ('%'||to_char({args0Value})||'%')");
        public override string ExpressionLambdaToSqlMemberAccessTimeSpan(MemberExpression exp, ExpTSC tsc)
        {
            if (exp.Expression == null)
            {
                switch (exp.Member.Name)
                {
                case "Zero": return("numtodsinterval(0,'second')");

                case "MinValue": return("numtodsinterval(-233720368.5477580,'second')");

                case "MaxValue": return("numtodsinterval(233720368.5477580,'second')");
                }
                return(null);
            }
            var left = ExpressionLambdaToSql(exp.Expression, tsc);

            switch (exp.Member.Name)
            {
            case "Days": return($"extract(day from {left})");

            case "Hours": return($"extract(hour from {left})");

            case "Milliseconds": return($"cast(substr(extract(second from {left})-floor(extract(second from {left})),3,3) as number)");

            case "Minutes": return($"extract(minute from {left})");

            case "Seconds": return($"floor(extract(second from {left}))");

            case "Ticks": return($"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*10000000");

            case "TotalDays": return($"extract(day from {left})");

            case "TotalHours": return($"(extract(day from {left})*24+extract(hour from {left}))");

            case "TotalMilliseconds": return($"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))*1000");

            case "TotalMinutes": return($"(extract(day from {left})*1440+extract(hour from {left})*60+extract(minute from {left}))");

            case "TotalSeconds": return($"(extract(day from {left})*86400+extract(hour from {left})*3600+extract(minute from {left})*60+extract(second from {left}))");
            }
            return(null);
        }
        public override string ExpressionLambdaToSqlMemberAccessDateTime(MemberExpression exp, ExpTSC tsc)
        {
            if (exp.Expression == null)
            {
                switch (exp.Member.Name)
                {
                case "Now": return(_common.Now);

                case "UtcNow": return(_common.NowUtc);

                case "Today": return("trunc(systimestamp)");

                case "MinValue": return("to_timestamp('0001-01-01 00:00:00','YYYY-MM-DD HH24:MI:SS.FF6')");

                case "MaxValue": return("to_timestamp('9999-12-31 23:59:59','YYYY-MM-DD HH24:MI:SS.FF6')");
                }
                return(null);
            }
            var left = ExpressionLambdaToSql(exp.Expression, tsc);

            switch (exp.Member.Name)
            {
            case "Date": return($"trunc({left})");

            case "TimeOfDay": return($"({left}-trunc({left}))");

            case "DayOfWeek": return($"case when to_char({left},'D')='7' then 0 else cast(to_char({left},'D') as number) end");

            case "Day": return($"cast(to_char({left},'DD') as number)");

            case "DayOfYear": return($"cast(to_char({left},'DDD') as number)");

            case "Month": return($"cast(to_char({left},'MM') as number)");

            case "Year": return($"cast(to_char({left},'YYYY') as number)");

            case "Hour": return($"cast(to_char({left},'HH24') as number)");

            case "Minute": return($"cast(to_char({left},'MI') as number)");

            case "Second": return($"cast(to_char({left},'SS') as number)");

            case "Millisecond": return($"cast(to_char({left},'FF3') as number)");

            case "Ticks": return($"cast(to_char({left},'FF7') as number)");
            }
            return(null);
        }
        public override string ExpressionLambdaToSqlOther(Expression exp, ExpTSC tsc)
        {
            Func <Expression, string> getExp = exparg => ExpressionLambdaToSql(exparg, tsc);

            switch (exp.NodeType)
            {
            case ExpressionType.ArrayLength:
                var arrOper = (exp as UnaryExpression)?.Operand;
                if (arrOper.Type == typeof(byte[]))
                {
                    return($"dbms_lob.getlength({getExp(arrOper)})");
                }
                break;

            case ExpressionType.Convert:
                var operandExp = (exp as UnaryExpression)?.Operand;
                var gentype    = exp.Type.NullableTypeOrThis();
                if (gentype != operandExp.Type.NullableTypeOrThis())
                {
                    switch (exp.Type.NullableTypeOrThis().ToString())
                    {
                    //case "System.Boolean": return $"({getExp(operandExp)} not in ('0','false'))";
                    case "System.Byte": return($"cast({getExp(operandExp)} as number)");

                    case "System.Char": return($"substr(to_char({getExp(operandExp)}), 1, 1)");

                    case "System.DateTime": return($"to_timestamp({getExp(operandExp)},'YYYY-MM-DD HH24:MI:SS.FF6')");

                    case "System.Decimal": return($"cast({getExp(operandExp)} as number)");

                    case "System.Double": return($"cast({getExp(operandExp)} as number)");

                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                    case "System.SByte": return($"cast({getExp(operandExp)} as number)");

                    case "System.Single": return($"cast({getExp(operandExp)} as number)");

                    case "System.String": return($"to_char({getExp(operandExp)})");

                    case "System.UInt16":
                    case "System.UInt32":
                    case "System.UInt64": return($"cast({getExp(operandExp)} as number)");

                    case "System.Guid":
                        if (tsc.mapType == typeof(byte[]))
                        {
                            return($"hextoraw({getExp(operandExp)})");
                        }
                        return($"to_char({getExp(operandExp)})");
                    }
                }
                break;

            case ExpressionType.Call:
                var callExp = exp as MethodCallExpression;

                switch (callExp.Method.Name)
                {
                case "Parse":
                case "TryParse":
                    switch (callExp.Method.DeclaringType.NullableTypeOrThis().ToString())
                    {
                    //case "System.Boolean": return $"({getExp(callExp.Arguments[0])} not in ('0','false'))";
                    case "System.Byte": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.Char": return($"substr(to_char({getExp(callExp.Arguments[0])}), 1, 1)");

                    case "System.DateTime": return($"to_timestamp({getExp(callExp.Arguments[0])},'YYYY-MM-DD HH24:MI:SS.FF6')");

                    case "System.Decimal": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.Double": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                    case "System.SByte": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.Single": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.UInt16":
                    case "System.UInt32":
                    case "System.UInt64": return($"cast({getExp(callExp.Arguments[0])} as number)");

                    case "System.Guid":
                        if (tsc.mapType == typeof(byte[]))
                        {
                            return($"hextoraw({getExp(callExp.Arguments[0])})");
                        }
                        return($"to_char({getExp(callExp.Arguments[0])})");
                    }
                    return(null);

                case "NewGuid":
                    return(null);

                case "Next":
                    if (callExp.Object?.Type == typeof(Random))
                    {
                        return("cast(dbms_random.value*1000000000 as smallint)");
                    }
                    return(null);

                case "NextDouble":
                    if (callExp.Object?.Type == typeof(Random))
                    {
                        return("dbms_random.value");
                    }
                    return(null);

                case "Random":
                    if (callExp.Method.DeclaringType.IsNumberType())
                    {
                        return("dbms_random.value");
                    }
                    return(null);

                case "ToString":
                    if (callExp.Object != null)
                    {
                        return(callExp.Arguments.Count == 0 ? $"to_char({getExp(callExp.Object)})" : null);
                    }
                    return(null);
                }

                var objExp  = callExp.Object;
                var objType = objExp?.Type;
                if (objType?.FullName == "System.Byte[]")
                {
                    return(null);
                }

                var argIndex = 0;
                if (objType == null && callExp.Method.DeclaringType == typeof(Enumerable))
                {
                    objExp  = callExp.Arguments.FirstOrDefault();
                    objType = objExp?.Type;
                    argIndex++;

                    if (objType == typeof(string))
                    {
                        switch (callExp.Method.Name)
                        {
                        case "First":
                        case "FirstOrDefault":
                            return($"substr({getExp(callExp.Arguments[0])}, 1, 1)");
                        }
                    }
                }
                if (objType == null)
                {
                    objType = callExp.Method.DeclaringType;
                }
                if (objType != null || objType.IsArrayOrList())
                {
                    if (argIndex >= callExp.Arguments.Count)
                    {
                        break;
                    }
                    tsc.SetMapColumnTmp(null);
                    var args1       = getExp(callExp.Arguments[argIndex]);
                    var oldMapType  = tsc.SetMapTypeReturnOld(tsc.mapTypeTmp);
                    var oldDbParams = tsc.SetDbParamsReturnOld(null);
                    var left        = objExp == null ? null : getExp(objExp);
                    tsc.SetMapColumnTmp(null).SetMapTypeReturnOld(oldMapType);
                    tsc.SetDbParamsReturnOld(oldDbParams);
                    switch (callExp.Method.Name)
                    {
                    case "Contains":
                        //判断 in //在各大 Provider AdoProvider 中已约定,500元素分割, 3空格\r\n4空格
                        return($"(({args1}) in {left.Replace(",   \r\n    \r\n", $") \r\n OR ({args1}) in (")})");
                    }
                }
                break;

            case ExpressionType.NewArrayInit:
                var arrExp = exp as NewArrayExpression;
                var arrSb  = new StringBuilder();
                arrSb.Append("(");
                for (var a = 0; a < arrExp.Expressions.Count; a++)
                {
                    if (a > 0)
                    {
                        arrSb.Append(",");
                    }
                    if (a % 500 == 499)
                    {
                        arrSb.Append("   \r\n    \r\n");                     //500元素分割, 3空格\r\n4空格
                    }
                    arrSb.Append(getExp(arrExp.Expressions[a]));
                }
                if (arrSb.Length == 1)
                {
                    arrSb.Append("NULL");
                }
                return(arrSb.Append(")").ToString());

            case ExpressionType.ListInit:
                var listExp = exp as ListInitExpression;
                var listSb  = new StringBuilder();
                listSb.Append("(");
                for (var a = 0; a < listExp.Initializers.Count; a++)
                {
                    if (listExp.Initializers[a].Arguments.Any() == false)
                    {
                        continue;
                    }
                    if (a > 0)
                    {
                        listSb.Append(",");
                    }
                    listSb.Append(getExp(listExp.Initializers[a].Arguments.FirstOrDefault()));
                }
                if (listSb.Length == 1)
                {
                    listSb.Append("NULL");
                }
                return(listSb.Append(")").ToString());

            case ExpressionType.New:
                var newExp = exp as NewExpression;
                if (typeof(IList).IsAssignableFrom(newExp.Type))
                {
                    if (newExp.Arguments.Count == 0)
                    {
                        return("(NULL)");
                    }
                    if (typeof(IEnumerable).IsAssignableFrom(newExp.Arguments[0].Type) == false)
                    {
                        return("(NULL)");
                    }
                    return(getExp(newExp.Arguments[0]));
                }
                return(null);
            }
            return(null);
        }