public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) { if (expression == null && buildInfo != null) { if (buildInfo.Parent is SelectManyBuilder.SelectManyContext) { var sm = (SelectManyBuilder.SelectManyContext)buildInfo.Parent; var ctype = typeof(ContextHelper <>).MakeGenericType(_key.Lambda.Parameters[0].Type); var helper = (IContextHelper)Activator.CreateInstance(ctype); var expr = helper.GetContext( Sequence.Expression, _key.Lambda.Parameters[0], Expression.PropertyOrField(sm.Lambda.Parameters[0], "Key"), _key.Lambda.Body); return(Builder.BuildSequence(new BuildInfo(buildInfo, expr))); } //if (buildInfo.Parent == this) { var ctype = typeof(ContextHelper <>).MakeGenericType(_key.Lambda.Parameters[0].Type); var helper = (IContextHelper)Activator.CreateInstance(ctype); var expr = helper.GetContext( _sequenceExpr, _key.Lambda.Parameters[0], Expression.PropertyOrField(buildInfo.Expression, "Key"), _key.Lambda.Body); var ctx = Builder.BuildSequence(new BuildInfo(buildInfo, expr)); ctx.SelectQuery.Properties.Add(Tuple.Create("from_group_by", SelectQuery)); return(ctx); } //return this; } if (level != 0) { var levelExpression = expression.GetLevelExpression(level); if (levelExpression.NodeType == ExpressionType.MemberAccess) { var ma = (MemberExpression)levelExpression; if (ma.Member.Name == "Key" && ma.Member.DeclaringType == _groupingType) { return(ReferenceEquals(levelExpression, expression) ? _key.GetContext(null, 0, buildInfo) : _key.GetContext(expression, level + 1, buildInfo)); } } } throw new NotImplementedException(); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { if (!methodCall.IsQueryable("GroupBy")) { return(false); } var body = ((LambdaExpression)methodCall.Arguments[1].Unwrap()).Body.Unwrap(); if (body.NodeType == ExpressionType.MemberInit) { var mi = (MemberInitExpression)body; bool throwExpr; if (mi.NewExpression.Arguments.Count > 0 || mi.Bindings.Count == 0) { throwExpr = true; } else { throwExpr = mi.Bindings.Any(b => b.BindingType != MemberBindingType.Assignment); } if (throwExpr) { throw new NotSupportedException("Explicit construction of entity type '{0}' in group by is not allowed.".Args(body.Type)); } } return(methodCall.Arguments[methodCall.Arguments.Count - 1].Unwrap().NodeType == ExpressionType.Lambda); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequenceExpr = methodCall.Arguments[0]; var sequence = builder.BuildSequence(new BuildInfo(buildInfo, sequenceExpr)); var groupingType = methodCall.Type.GetGenericArgumentsEx()[0]; var keySelector = (LambdaExpression)methodCall.Arguments[1].Unwrap(); var elementSelector = (LambdaExpression)methodCall.Arguments[2].Unwrap(); if (methodCall.Arguments[0].NodeType == ExpressionType.Call) { var call = (MethodCallExpression)methodCall.Arguments[0]; if (call.Method.Name == "Select") { var type = ((LambdaExpression)call.Arguments[1].Unwrap()).Body.Type; if (type.IsGenericTypeEx() && type.GetGenericTypeDefinition() == typeof(ExpressionBuilder.GroupSubQuery <,>)) { sequence = new SubQueryContext(sequence); } } } var key = new KeyContext(buildInfo.Parent, keySelector, sequence); var groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.GroupBy.Items.Count > 0 || groupSql.Any(_ => !(_.Sql is SqlField || _.Sql is SelectQuery.Column))) { sequence = new SubQueryContext(sequence); key = new KeyContext(buildInfo.Parent, keySelector, sequence); groupSql = builder.ConvertExpressions(key, keySelector.Body.Unwrap(), ConvertFlags.Key); } foreach (var sql in groupSql) { sequence.SelectQuery.GroupBy.Expr(sql.Sql); } new QueryVisitor().Visit(sequence.SelectQuery.From, e => { if (e.ElementType == QueryElementType.JoinedTable) { var jt = (SelectQuery.JoinedTable)e; if (jt.JoinType == SelectQuery.JoinType.Inner) { jt.IsWeak = false; } } }); var element = new SelectContext(buildInfo.Parent, elementSelector, sequence /*, key*/); var groupBy = new GroupByContext(buildInfo.Parent, sequenceExpr, groupingType, sequence, key, element); return(groupBy); }
protected override SequenceConvertInfo Convert( ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) { return(null); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); if (sequence.SelectQuery.Select.IsDistinct || sequence.SelectQuery.Select.TakeValue != null || sequence.SelectQuery.Select.SkipValue != null || !sequence.SelectQuery.GroupBy.IsEmpty) { sequence = new SubQueryContext(sequence); } if (sequence.SelectQuery.OrderBy.Items.Count > 0) { if (sequence.SelectQuery.Select.TakeValue == null && sequence.SelectQuery.Select.SkipValue == null) { sequence.SelectQuery.OrderBy.Items.Clear(); } else { sequence = new SubQueryContext(sequence); } } var context = new AggregationContext(buildInfo.Parent, sequence, methodCall); var sql = sequence.ConvertToSql(null, 0, ConvertFlags.Field).Select(_ => _.Sql).ToArray(); if (sql.Length == 1 && sql[0] is SelectQuery) { var query = (SelectQuery)sql[0]; if (query.Select.Columns.Count == 1) { var join = SelectQuery.OuterApply(query); context.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable); sql[0] = query.Select.Columns[0]; } } context.Sql = context.SelectQuery; context.FieldIndex = context.SelectQuery.Select.Add( new SqlFunction(methodCall.Type, methodCall.Method.Name, sql)); return(context); }
public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) { throw new NotImplementedException(); }
protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { return(methodCall.IsQueryable(MethodNames)); }
public BuildInfo(BuildInfo buildInfo, Expression expression, SelectQuery selectQuery) : this(buildInfo.Parent, expression, selectQuery) { SequenceInfo = buildInfo; CreateSubQuery = buildInfo.CreateSubQuery; }