Example #1
0
        private Expression JoinMethod(MethodCallExpression node)
        {
            WriteAppendAtFix(() =>
            {
                buildJoin = true;

                buildFrom = true;

                base.Visit(node.Arguments[0]);

                buildFrom = true;

                base.Visit(node.Arguments[1]);

                buildFrom = false;
            }, () =>
            {
                SQLWriter.Write(" ON ");

                buildFrom = false;

                base.Visit(node.Arguments[2]);

                SQLWriter.Equal();

                base.Visit(node.Arguments[3]);
            });

            return(node);
        }
Example #2
0
        private void BuildSingleField(string methodName, string prefix, ITableRegions regions)
        {
            IEnumerable <KeyValuePair <string, string> > names = regions.ReadOrWrites;

            if (buildCast)
            {
                names = names.Where(kv => InCastList(kv.Key));
            }

            if (names.Count() == 0)
            {
                throw new DException("未指定查询字段!");
            }

            names.ForEach((kv, index) =>
            {
                if (index > 0)
                {
                    SQLWriter.Delimiter();
                }

                SQLWriter.Write(methodName);
                SQLWriter.OpenBrace();

                SQLWriter.Name(prefix, kv.Value);

                SQLWriter.CloseBrace();
                SQLWriter.As(kv.Key);
            });
        }
Example #3
0
        private Expression SingleFieldMethod(MethodCallExpression node)
        {
            string name = node.Method.Name;

            if (name == MethodCall.Average)
            {
                name = "Avg";
            }
            else if (name == MethodCall.LongCount)
            {
                name = MethodCall.Count;
            }

            isAggregation = true;

            if (node.Arguments.Count > 1 || !(isNoParameterCount = name == MethodCall.Count))
            {
                _MethodLevel += 1;
            }

            if (buildSelect)
            {
                buildSelect = false;

                if (node.Arguments.Count > 1 || name == MethodCall.Count)
                {
                    return(SingleFieldTwoArgOrCountMethod(name, node));
                }

                return(SingleFieldOnlyArgMethod(name, node.Arguments[0]));
            }

            if (node.Arguments.Count > 1 || name == MethodCall.Count)
            {
                SQLWriter.Write(name);
                SQLWriter.OpenBrace();
                if (node.Arguments.Count > 1)
                {
                    base.Visit(node.Arguments[1]);
                }
                else
                {
                    SQLWriter.Write("1");
                }
                SQLWriter.CloseBrace();
                return(node);
            }

            return(BuildSingleOneArgField(name, node));
        }
Example #4
0
        protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
        {
            var regions = MakeTableRegions(typeof(T));

            if (regions.ReadWrites.TryGetValue(node.Member.Name, out string value))
            {
                SQLWriter.Name(value);
                SQLWriter.Write("=");

                return(base.VisitMemberAssignment(node));
            }

            throw new ExpressionNotSupportedException($"{node.Member.Name}字段不可写!");
        }
Example #5
0
        private Expression SingleFieldTwoArgOrCountMethod(string name, MethodCallExpression node)
        {
            WriteAppendAtFix(() =>
            {
                SQLWriter.Select();

                SQLWriter.Write(name);
                SQLWriter.OpenBrace();

                if (node.Arguments.Count > 1)
                {
                    base.Visit(node.Arguments[1]);
                }
                else
                {
                    SQLWriter.Write("1");
                }

                SQLWriter.CloseBrace();

                if (SQLWriter.IsUnion)
                {
                    SQLWriter.From();
                    SQLWriter.OpenBrace();
                }
            }, () => base.Visit(node.Arguments[0]));

            if (SQLWriter.IsUnion)
            {
                SQLWriter.CloseBrace();
                SQLWriter.WhiteSpace();

                SQLWriter.TableName("CTE_UNION");
            }

            return(node);
        }
Example #6
0
        /// <summary>
        ///  System.Linq.Queryable 的函数
        /// </summary>
        /// <param name="node">表达式</param>
        /// <returns></returns>
        protected virtual Expression VisitQueryableMethodCall(MethodCallExpression node)
        {
            //? 函数名称
            string name = node.Method.Name;

            if (node.Arguments.Count > 1 ?
                !(name == MethodCall.Take || name == MethodCall.Skip || name == MethodCall.TakeLast || name == MethodCall.SkipLast) :
                (name == MethodCall.Sum || name == MethodCall.Max || name == MethodCall.Min || name == MethodCall.Average)
                )
            {
                _MethodLevel += 1;
            }

            switch (name)
            {
            case MethodCall.Any:

                if (Parent?.BuildWhere ?? BuildWhere)
                {
                    return(VisitExists(node));
                }

                if (buildSelect)
                {
                    SQLWriter.Select();
                }

                SQLWriter.Write("CASE WHEN ");

                VisitExists(node);

                SQLWriter.Write(" THEN ");
                SQLWriter.Parameter("__variable_true", true);
                SQLWriter.Write(" ELSE ");
                SQLWriter.Parameter("__variable_false", false);
                SQLWriter.Write(" END");

                return(node);

            case MethodCall.All:

                if (Parent?.BuildWhere ?? BuildWhere)
                {
                    SQLWriter.OpenBrace();

                    VisitMethodAll(node);

                    SQLWriter.CloseBrace();
                }
                else
                {
                    if (buildSelect)
                    {
                        SQLWriter.Select();
                    }

                    SQLWriter.Write("CASE WHEN ");

                    VisitMethodAll(node);

                    SQLWriter.Write(" THEN ");
                    SQLWriter.Parameter("__variable_true", true);
                    SQLWriter.Write(" ELSE ");
                    SQLWriter.Parameter("__variable_false", false);
                    SQLWriter.Write(" END");
                }
                return(node);

            case MethodCall.ElementAt:
            case MethodCall.ElementAtOrDefault:

                base.Visit(node.Arguments[0]);

                int index = (int)node.Arguments[1].GetValueFromExpression();

                if (index < 0)
                {
                    throw new IndexOutOfRangeException();
                }

                if (SQLWriter.Take > 0 && index < SQLWriter.Take)
                {
                    throw new IndexOutOfRangeException();
                }

                SQLWriter.Take = 1;

                SQLWriter.Skip += index;

                return(node);

            case MethodCall.Take:
            case MethodCall.TakeLast:

                if (isAggregation)
                {
                    throw new ExpressionNotSupportedException($"使用聚合函数时,禁止使用分页函数({name})!");
                }

                if (name == MethodCall.TakeLast)
                {
                    isOrderByReverse ^= true;
                }

                base.Visit(node.Arguments[0]);

                if (!isContainsOrderBy && name == MethodCall.TakeLast)
                {
                    throw new ExpressionNotSupportedException($"使用函数({name})时,必须使用排序函数(OrderBy/OrderByDescending)!");
                }

                int take = (int)node.Arguments[1].GetValueFromExpression();

                if (take < 0)
                {
                    throw new ArgumentOutOfRangeException($"使用{name}函数,参数值不能小于零!");
                }

                if (SQLWriter.Take > 0 && take < SQLWriter.Take)
                {
                    throw new IndexOutOfRangeException();
                }

                if (SQLWriter.Take == 0)
                {
                    SQLWriter.Take = take;
                }

                return(node);

            case MethodCall.Single:
            case MethodCall.SingleOrDefault:
            case MethodCall.First:
            case MethodCall.FirstOrDefault:

                // TOP(1)
                SQLWriter.Take = 1;

                if (node.Arguments.Count > 1)
                {
                    MakeWhere(node);
                }
                else
                {
                    base.Visit(node.Arguments[0]);
                }

                return(node);

            case MethodCall.Last:
            case MethodCall.LastOrDefault:

                // TOP(..)
                SQLWriter.Take = 1;

                isOrderByReverse ^= true;

                if (node.Arguments.Count > 1)
                {
                    MakeWhere(node);
                }
                else
                {
                    base.Visit(node.Arguments[0]);
                }

                if (!isContainsOrderBy)
                {
                    throw new ExpressionNotSupportedException($"使用函数({name})时,必须使用排序函数(OrderBy/OrderByDescending)!");
                }

                return(node);

            case MethodCall.Skip:
            case MethodCall.SkipLast:

                if (isAggregation)
                {
                    throw new ExpressionNotSupportedException($"使用聚合函数时,禁止使用分页函数({name})!");
                }

                if (name == MethodCall.SkipLast)
                {
                    isOrderByReverse ^= true;
                }

                base.Visit(node.Arguments[0]);

                if (!isContainsOrderBy && name == MethodCall.SkipLast)
                {
                    throw new ExpressionNotSupportedException($"使用函数({name})时,必须使用排序函数(OrderBy/OrderByDescending)!");
                }

                int skip = (int)node.Arguments[1].GetValueFromExpression();

                if (skip < 0)
                {
                    throw new ArgumentOutOfRangeException($"使用({name})函数,参数值不能小于零!");
                }

                SQLWriter.Skip += skip;

                return(node);

            case MethodCall.Distinct:

                isDistinct = true;

                return(base.Visit(node.Arguments[0]));

            case MethodCall.Reverse:

                isOrderByReverse ^= true;

                base.Visit(node.Arguments[0]);

                if (!isContainsOrderBy)
                {
                    throw new ExpressionNotSupportedException($"使用函数({name})时,必须使用排序函数(OrderBy/OrderByDescending)!");
                }

                return(node);

            case MethodCall.OrderBy:
            case MethodCall.ThenBy:
            case MethodCall.OrderByDescending:
            case MethodCall.ThenByDescending:

                isContainsOrderBy = true;

                base.Visit(node.Arguments[0]);

                if (isAggregation)
                {
                    return(node);
                }

                SQLWriter.IsOrderBy = true;

                _orderBySwitch.Execute();

                base.Visit(node.Arguments[1]);

                if (isOrderByReverse ^ name.EndsWith("Descending"))
                {
                    SQLWriter.WriteDesc();
                }
                SQLWriter.IsOrderBy = false;
                return(node);

            case MethodCall.Where:
            case MethodCall.TakeWhile:
                return(MakeWhere(node));

            case MethodCall.SkipWhile:
                return(WrapNot(() =>
                {
                    return MakeWhere(node);
                }));

            case MethodCall.Select:

                if (_MethodLevel > 1)
                {
                    throw new ExpressionNotSupportedException($"请将函数({name})置于查询最后一个包含入参的函数之后!");
                }

                if (isNoParameterCount)
                {
                    return(base.Visit(node.Arguments[0]));
                }

                buildSelect = false;

                SQLWriter.Select();

                buildFrom = false;

                WriteAppendAtFix(() =>
                {
                    if (isDistinct)
                    {
                        SQLWriter.Distinct();
                    }

                    buildFrom = true;
                    base.Visit(node.Arguments[1]);
                    buildFrom = false;
                }, () => base.Visit(node.Arguments[0]));

                return(node);

            case MethodCall.Max:
            case MethodCall.Min:
            case MethodCall.Sum:
            case MethodCall.Count:
            case MethodCall.Average:
            case MethodCall.LongCount:
                return(SingleFieldMethod(node));

            case MethodCall.Join:
                return(JoinMethod(node));

            case MethodCall.Union:
            case MethodCall.Concat:
            case MethodCall.Intersect:

                buildSelect = false;

                SQLWriter.IsUnion = false;

                VisitBuilder(node.Arguments[0]);

                if (name == MethodCall.Intersect)
                {
                    SQLWriter.Write(" INTERSECT ");
                }
                else
                {
                    SQLWriter.Write(MethodCall.Union == name ? " UNION " : " UNION ALL ");
                }

                VisitBuilder(node.Arguments[1]);

                SQLWriter.IsUnion = true;

                return(node);

            case MethodCall.Cast:

                Type type = node.Type.GetGenericArguments().First();

                if (type.IsValueType || type == typeof(string) || typeof(IEnumerable).IsAssignableFrom(type))
                {
                    throw new TypeAccessInvalidException($"{name}函数泛型参数类型不能是值类型、字符串类型或迭代类型!");
                }

                var castToType = node.Arguments
                                 .Select(x => x.Type)
                                 .First();

                if (node.Type == castToType)
                {
                    return(base.Visit(node.Arguments[0]));
                }

                useCast = true;

                _TypeCache.GetOrAdd(type, _ => GetInitialType(castToType));

                if (!buildSelect)
                {
                    return(base.Visit(node.Arguments[0]));   //? 说明Cast函数在Select函数之前,不需要进行函数分析!
                }
                var entry = RuntimeTypeCache.Instance.GetCache(type);

                if (_CastList is null)
                {
                    _CastList = entry.PropertyStores
                                .Select(x => x.Name.ToLower())
                                .ToList();
                }
                else     //? 取交集
                {
                    _CastList = _CastList
                                .Intersect(entry.PropertyStores.Select(x => x.Name.ToLower()))
                                .ToList();
                }

                if (_CastList.Count == 0)
                {
                    throw new DException("未指定查询字段!");
                }

                buildCast = true;

                return(base.Visit(node.Arguments[0]));

            default:
                return(VisitFormatterMethodCall(node));
            }
        }