Пример #1
0
        protected override Expression VisitMemberAccess(MemberExpression m)
        {
            Expression source = this.Visit(m.Expression);

            if (this.mapping.IsRelationship(m.Member))
            {
                ProjectionExpression projection = (ProjectionExpression)this.Visit(this.mapping.GetMemberExpression(source, m.Member));
                if (this.currentFrom != null && this.mapping.IsSingletonRelationship(m.Member))
                {
                    // convert singleton associations directly to OUTER APPLY
                    projection = projection.AddOuterJoinTest();
                    Expression newFrom = new JoinExpression(JoinType.OuterApply, this.currentFrom, projection.Source, null);
                    this.currentFrom = newFrom;
                    return(projection.Projector);
                }
                return(projection);
            }
            else
            {
                Expression       result = QueryBinder.BindMember(source, m.Member);
                MemberExpression mex    = result as MemberExpression;
                if (mex != null && mex.Member == m.Member && mex.Expression == m.Expression)
                {
                    return(m);
                }
                return(result);
            }
        }
Пример #2
0
        protected virtual Expression BindSelectMany(Type resultType, Expression source,
                                                    LambdaExpression collectionSelector, LambdaExpression resultSelector)
        {
            ProjectionExpression projection = VisitSequence(source);

            map[collectionSelector.Parameters[0]] = projection.Projector;

            Expression collection = collectionSelector.Body;

            // check for DefaultIfEmpty
            bool defaultIfEmpty      = false;
            MethodCallExpression mcs = collection as MethodCallExpression;

            if (mcs != null && mcs.Method.Name == "DefaultIfEmpty" && mcs.Arguments.Count == 1 &&
                (mcs.Method.DeclaringType == typeof(Queryable) || mcs.Method.DeclaringType == typeof(Enumerable)))
            {
                collection     = mcs.Arguments[0];
                defaultIfEmpty = true;
            }

            ProjectionExpression collectionProjection = VisitSequence(collection);
            bool     isTable  = collectionProjection.Source.From is TableExpression;
            JoinType joinType = isTable
                                    ? JoinType.CrossJoin
                                    : defaultIfEmpty ? JoinType.OuterApply : JoinType.CrossApply;

            if (joinType == JoinType.OuterApply)
            {
                collectionProjection = collectionProjection.AddOuterJoinTest();
            }
            JoinExpression join = new JoinExpression(joinType, projection.Source, collectionProjection.Source, null);

            var alias = GetNextAlias();
            ProjectedColumns pc;

            if (resultSelector == null)
            {
                pc = ProjectColumns(collectionProjection.Projector, alias, projection.Source.Alias,
                                    collectionProjection.Source.Alias);
            }
            else
            {
                map[resultSelector.Parameters[0]] = projection.Projector;
                map[resultSelector.Parameters[1]] = collectionProjection.Projector;
                Expression result = Visit(resultSelector.Body);
                pc = ProjectColumns(result, alias, projection.Source.Alias, collectionProjection.Source.Alias);
            }
            return(new ProjectionExpression(
                       new SelectExpression(alias, pc.Columns, join, null),
                       pc.Projector
                       ));
        }