Beispiel #1
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("LoadWith"));
 }
Beispiel #2
0
        static IEnumerable <MemberInfo> GetAssociations(ExpressionBuilder builder, Expression expression)
        {
            MemberInfo lastMember = null;

            for (;;)
            {
                switch (expression.NodeType)
                {
                case ExpressionType.Parameter:
                    if (lastMember == null)
                    {
                        goto default;
                    }
                    yield break;

                case ExpressionType.Call:
                {
                    if (lastMember == null)
                    {
                        goto default;
                    }

                    var cexpr = (MethodCallExpression)expression;
                    var expr  = cexpr.Object;

                    if (expr == null)
                    {
                        if (cexpr.Arguments.Count == 0)
                        {
                            goto default;
                        }

                        expr = cexpr.Arguments[0];
                    }

                    if (expr.NodeType != ExpressionType.MemberAccess)
                    {
                        goto default;
                    }

                    var member = ((MemberExpression)expr).Member;
                    var mtype  = member.GetMemberType();

                    if (lastMember.ReflectedTypeEx() != mtype.GetItemType())
                    {
                        goto default;
                    }

                    expression = expr;

                    break;
                }

                case ExpressionType.MemberAccess:
                {
                    var mexpr  = (MemberExpression)expression;
                    var member = lastMember = mexpr.Member;
                    var attr   = builder.MappingSchema.GetAttribute <AssociationAttribute>(member);

                    if (attr == null)
                    {
                        throw new LinqToDBException(
                                  string.Format("Member '{0}' is not an association.", expression));
                    }

                    yield return(member);

                    expression = mexpr.Expression;

                    break;
                }

                case ExpressionType.ArrayIndex:
                {
                    expression = ((BinaryExpression)expression).Left;
                    break;
                }

                case ExpressionType.Extension:
                {
                    if (expression is GetItemExpression)
                    {
                        expression = ((GetItemExpression)expression).Expression;
                        break;
                    }

                    goto default;
                }

                default:
                {
                    throw new LinqToDBException(
                              string.Format("Expression '{0}' is not an association.", expression));
                }
                }
            }
        }
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence           = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (!sequence.SelectQuery.GroupBy.IsEmpty)
            {
                sequence = new SubQueryContext(sequence);
            }

            var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence);
            var expr    = collectionSelector.Body.Unwrap();

            var collectionInfo = new BuildInfo(context, expr, new SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);
            var leftJoin       = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext;
            var sql            = collection.SelectQuery;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != new QueryVisitor().Find(sql, e =>
                                                                 e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) ||
                                                                 e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) ||
                                                                 e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SelectQuery.Column)e).Parent));

            if (collection is JoinBuilder.GroupJoinSubQueryContext)
            {
                var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin;

                groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = SelectQuery.JoinType.Inner;
                groupJoin.SelectQuery.From.Tables[0].Joins[0].IsWeak   = false;
            }

            if (!newQuery)
            {
                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

            if (!crossApply)
            {
                if (!leftJoin)
                {
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, true);
                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
                else
                {
                    var join = SelectQuery.OuterApply(sql);
                    sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);

                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
            }

            if (collection is TableBuilder.TableContext)
            {
                var table = (TableBuilder.TableContext)collection;

                var join = table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0 ?
                           (leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql)) :
                           (leftJoin ? SelectQuery.LeftJoin(sql) : SelectQuery.InnerJoin(sql));

                join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);
                join.JoinedTable.CanConvertApply = false;

                sql.Where.SearchCondition.Conditions.Clear();

                var collectionParent = collection.Parent as TableBuilder.TableContext;

                // Association.
                //
                if (collectionParent != null && collectionInfo.IsAssociationBuilt)
                {
                    var ts = (SelectQuery.TableSource) new QueryVisitor().Find(sequence.SelectQuery.From, e =>
                    {
                        if (e.ElementType == QueryElementType.TableSource)
                        {
                            var t = (SelectQuery.TableSource)e;
                            return(t.Source == collectionParent.SqlTable);
                        }

                        return(false);
                    });

                    ts.Joins.Add(join.JoinedTable);
                }
                else
                {
                    sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                var join = leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql);
                sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }
Beispiel #4
0
 protected override SequenceConvertInfo Convert(
     ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
Beispiel #5
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Contains") && methodCall.Arguments.Count == 2);
 }
Beispiel #6
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            return(new ContainsContext(buildInfo.Parent, methodCall, sequence));
        }
Beispiel #7
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Where", "Having"));
 }
Beispiel #8
0
 public bool IsSequence(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(builder.IsSequence(new BuildInfo(buildInfo, ((MethodCallExpression)buildInfo.Expression).Arguments[0])));
 }
Beispiel #9
0
 public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
Beispiel #10
0
        public IBuildContext BuildSequence(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var call = (MethodCallExpression)buildInfo.Expression;

            return(new Context(builder.BuildSequence(new BuildInfo(buildInfo, call.Arguments[0]))));
        }
Beispiel #11
0
        public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo)
        {
            var call = buildInfo.Expression as MethodCallExpression;

            return(call != null && call.Method.Name == "GetContext");
        }