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); }
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); } }
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); }
/// <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)); } }
/// <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)); } }