Exemple #1
0
        private Expression SingleFieldOnlyArgMethod(string name, Expression node)
        {
            WriteAppendAtFix(() =>
            {
                SQLWriter.Select();

                BuildSingleOneArgField(name, node);

                if (SQLWriter.IsUnion)
                {
                    _fromSwitch.Execute();
                    SQLWriter.OpenBrace();
                    SQLWriter.AppendAt = -1;
                    SQLWriter.CloseBrace();
                    SQLWriter.WhiteSpace();
                    SQLWriter.TableName("CTE_UNION");
                }
            }, () => base.Visit(node));

            return(node);
        }
Exemple #2
0
        private void MakeSelectFrom(Type type)
        {
            var regions = MakeTableRegions(type);

            if (buildSelect)
            {
                buildSelect = false;

                SQLWriter.Select();

                if (isDistinct)
                {
                    SQLWriter.Distinct();
                }

                BuildColumns(regions);
            }

            if (buildFrom)
            {
                MakeFrom(regions);
            }
        }
Exemple #3
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);
        }
Exemple #4
0
        /// <summary>
        /// Queryable 拓展方法
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        protected virtual Expression VisitQueryableExtentionsMethodCall(MethodCallExpression node)
        {
            string name = node.Method.Name;

            switch (name)
            {
            case MethodCall.From:

                var value = (Func <ITableRegions, string>)node.Arguments[1].GetValueFromExpression();

                if (value == null)
                {
                    throw new DException("指定表名称不能为空!");
                }

                if (!buildFrom)
                {
                    base.Visit(node.Arguments[0]);
                }

                SetTableFactory(value);

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

                return(node);

            case MethodCall.TakeFirst:
            case MethodCall.TakeFirstOrDefault:
            case MethodCall.TakeSingle:
            case MethodCall.TakeSingleOrDefault:

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

                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.TakeLast:
            case MethodCall.TakeLastOrDefault:

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

                isOrderByReverse ^= true;

                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]));

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

                return(node);

            default:
                return(VisitFormatterMethodCall(node));
            }
        }
Exemple #5
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));
            }
        }