Пример #1
0
 public void AddJoin(AdditionalFromClause join)
 {
     AdditionalJoins.Add(join);
 }
Пример #2
0
        public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
        {
            _queryParts.AddFromPart(fromClause);

            base.VisitAdditionalFromClause(fromClause, queryModel, index);
        }
Пример #3
0
        public override void VisitAdditionalFromClause(
            AdditionalFromClause fromClause, QueryModel queryModel, int index)
        {
            Check.NotNull(fromClause, nameof(fromClause));
            Check.NotNull(queryModel, nameof(queryModel));

            base.VisitAdditionalFromClause(fromClause, queryModel, index);

            RequiresClientSelectMany = true;

            var selectExpression = TryGetQuery(fromClause);

            if (selectExpression != null &&
                selectExpression.Tables.Count == 1)
            {
                var previousQuerySource = FindPreviousQuerySource(queryModel, index);

                if (previousQuerySource != null &&
                    !RequiresClientJoin)
                {
                    var previousSelectExpression = TryGetQuery(previousQuerySource);

                    if (previousSelectExpression != null)
                    {
                        if (!QueryCompilationContext.QuerySourceRequiresMaterialization(previousQuerySource))
                        {
                            previousSelectExpression.ClearProjection();
                            previousSelectExpression.IsProjectStar = false;
                        }

                        var readerOffset = previousSelectExpression.Projection.Count;

                        var correlated = selectExpression.IsCorrelated();

                        if (correlated)
                        {
                            if (!QueryCompilationContext.IsLateralJoinSupported)
                            {
                                return;
                            }

                            previousSelectExpression
                            .AddLateralJoin(selectExpression.Tables.First(), selectExpression.Projection);
                        }
                        else
                        {
                            previousSelectExpression
                            .AddCrossJoin(selectExpression.Tables.First(), selectExpression.Projection);
                        }

                        QueriesBySource.Remove(fromClause);

                        Expression
                            = _queryFlattenerFactory
                              .Create(
                                  fromClause,
                                  QueryCompilationContext,
                                  LinqOperatorProvider.SelectMany,
                                  readerOffset)
                              .Flatten((MethodCallExpression)Expression);

                        RequiresClientSelectMany = false;
                    }
                }
            }

            if (RequiresClientSelectMany)
            {
                CheckClientEval(fromClause);
            }
        }
Пример #4
0
        private Expression RewriteNavigationsIntoJoins(
            QuerySourceReferenceExpression outerQuerySourceReferenceExpression,
            IEnumerable <INavigation> navigations,
            PropertyInfo member)
        {
            var querySourceReferenceExpression = outerQuerySourceReferenceExpression;
            var navigationJoins           = _navigationJoins;
            var optionalNavigationInChain = false;

            foreach (var navigation in navigations)
            {
                if (!navigation.ForeignKey.IsRequired)
                {
                    optionalNavigationInChain = true;
                }

                var targetEntityType = navigation.GetTargetType();

                if (navigation.IsCollection())
                {
                    _queryModel.MainFromClause.FromExpression = CreateEntityQueryable(targetEntityType);

                    var innerQuerySourceReferenceExpression
                        = new QuerySourceReferenceExpression(_queryModel.MainFromClause);

                    var leftKeyAccess = CreateKeyAccessExpression(
                        querySourceReferenceExpression,
                        navigation.IsDependentToPrincipal()
                            ? navigation.ForeignKey.Properties
                            : navigation.ForeignKey.PrincipalKey.Properties);

                    var rightKeyAccess = CreateKeyAccessExpression(
                        innerQuerySourceReferenceExpression,
                        navigation.IsDependentToPrincipal()
                            ? navigation.ForeignKey.PrincipalKey.Properties
                            : navigation.ForeignKey.Properties);

                    _queryModel.BodyClauses.Add(
                        new WhereClause(
                            CreateKeyComparisonExpression(leftKeyAccess, rightKeyAccess)));

                    return(_queryModel.MainFromClause.FromExpression);
                }

                var navigationJoin
                    = navigationJoins
                      .FirstOrDefault(nj =>
                                      nj.QuerySource == querySourceReferenceExpression.ReferencedQuerySource &&
                                      nj.Navigation == navigation);

                if (navigationJoin == null)
                {
                    QuerySourceReferenceExpression innerQuerySourceReferenceExpression;
                    var joinClause = BuildJoinFromNavigation(
                        querySourceReferenceExpression,
                        navigation,
                        targetEntityType,
                        optionalNavigationInChain,
                        out innerQuerySourceReferenceExpression);

                    var additionalBodyClauses = new List <IBodyClause>();
                    if (optionalNavigationInChain || !navigation.ForeignKey.IsRequired)
                    {
                        var groupJoinClause
                            = new GroupJoinClause(
                                  joinClause.ItemName + "_group",
                                  typeof(IEnumerable <>).MakeGenericType(targetEntityType.ClrType),
                                  joinClause);

                        var groupReferenceExpression = new QuerySourceReferenceExpression(groupJoinClause);

                        var defaultIfEmptyMainFromClause      = new MainFromClause(joinClause.ItemName + "_groupItem", joinClause.ItemType, groupReferenceExpression);
                        var newQuerySourceReferenceExpression = new QuerySourceReferenceExpression(defaultIfEmptyMainFromClause);

                        var defaultIfEmptyQueryModel = new QueryModel(
                            defaultIfEmptyMainFromClause,
                            new SelectClause(newQuerySourceReferenceExpression));
                        defaultIfEmptyQueryModel.ResultOperators.Add(new DefaultIfEmptyResultOperator(null));

                        var defaultIfEmptySubquery             = new SubQueryExpression(defaultIfEmptyQueryModel);
                        var defaultIfEmptyAdditionalFromClause = new AdditionalFromClause(joinClause.ItemName, joinClause.ItemType, defaultIfEmptySubquery);

                        additionalBodyClauses.Add(defaultIfEmptyAdditionalFromClause);

                        navigationJoins.Add(
                            navigationJoin
                                = new NavigationJoin(
                                      querySourceReferenceExpression.ReferencedQuerySource,
                                      navigation,
                                      groupJoinClause,
                                      additionalBodyClauses,
                                      optionalNavigationInChain,
                                      navigation.IsDependentToPrincipal(),
                                      new QuerySourceReferenceExpression(defaultIfEmptyAdditionalFromClause)));
                    }
                    else
                    {
                        navigationJoins.Add(
                            navigationJoin
                                = new NavigationJoin(
                                      querySourceReferenceExpression.ReferencedQuerySource,
                                      navigation,
                                      joinClause,
                                      additionalBodyClauses,
                                      optionalNavigationInChain,
                                      navigation.IsDependentToPrincipal(),
                                      innerQuerySourceReferenceExpression));
                    }
                }

                querySourceReferenceExpression = navigationJoin.QuerySourceReferenceExpression;
                navigationJoins = navigationJoin.NavigationJoins;
            }

            if (member == null)
            {
                return(querySourceReferenceExpression);
            }

            if (optionalNavigationInChain)
            {
                Expression memberAccessExpression = Expression.MakeMemberAccess(querySourceReferenceExpression, member);
                if (!member.PropertyType.IsNullableType())
                {
                    memberAccessExpression = Expression.Convert(memberAccessExpression, member.PropertyType.MakeNullable());
                }

                var constantNullExpression = member.PropertyType.IsNullableType()
                    ? Expression.Constant(null, member.PropertyType)
                    : Expression.Constant(null, member.PropertyType.MakeNullable());

                return(Expression.Condition(
                           Expression.NotEqual(
                               querySourceReferenceExpression,
                               Expression.Constant(null, querySourceReferenceExpression.Type)),
                           memberAccessExpression,
                           constantNullExpression));
            }
            return(Expression.MakeMemberAccess(querySourceReferenceExpression, member));
        }
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     throw new NotSupportedException("Additional from clauses not supported");
 }
Пример #6
0
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     throw new NotSupportedException("Additional froms not supported");
     //_queryBuilder.FromParts.Add(fromClause.ItemType.Name);
     base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
Пример #7
0
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     AppendLine();
     TransformingVisitor.StringBuilder.Append($"from {fromClause.ItemType.ShortDisplayName()} {fromClause.ItemName} in ");
     base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
 /// <summary>
 ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
 ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
 ///     any release. You should only use it directly in your code with extreme caution and knowing that
 ///     doing so can result in application failures when updating to a new Entity Framework Core release.
 /// </summary>
 public static GroupJoinClause TryGetFlattenedGroupJoinClause([NotNull] this AdditionalFromClause additionalFromClause)
 => (additionalFromClause.FromExpression is SubQueryExpression subQueryExpression &&
Пример #10
0
 public void SetUp()
 {
     _additionalFromClause = ExpressionHelper.CreateAdditionalFromClause();
     _cloneContext         = new CloneContext(new QuerySourceMapping());
 }
Пример #11
0
 /// <summary>
 /// Overrides the <see cref="QueryModelVisitorBase.VisitAdditionalFromClause(AdditionalFromClause, QueryModel, int)"/>.
 /// </summary>
 /// <param name="fromClause">The <see cref="AdditionalFromClause"/>.</param>
 /// <param name="queryModel">The <see cref="QueryModel"/>.</param>
 /// <param name="index">The index.</param>
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     throw new NotSupportedException($"Additional From clause is not supported: {fromClause.ToString()}.");
 }
 /// <summary>Visits an additional from clause.</summary>
 /// <param name="fromClause">From clause to be visited.</param>
 /// <param name="queryModel">Query model containing given from clause.</param>
 /// <param name="index">Index of the where clause in the query model.</param>
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     _visitor.Visit(fromClause.FromExpression);
     _from = _visitor.RetrieveComponent();
     base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
Пример #13
0
		public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
		{
			if (fromClause.FromExpression is MemberExpression)
			{
				var member = (MemberExpression) fromClause.FromExpression;

				if (member.Expression is QuerySourceReferenceExpression)
				{
					// It's a join
					var visitor = new HqlGeneratorExpressionTreeVisitor(_parameterAggregator);
					visitor.Visit(fromClause.FromExpression);

					HqlJoin joinNode = _hqlTreeBuilder.Join(
						visitor.GetHqlTreeNodes().Single(),
						_hqlTreeBuilder.Alias(fromClause.ItemName));

					_fromClause.AddChild(joinNode);
				}
			}

			base.VisitAdditionalFromClause(fromClause, queryModel, index);
		}
Пример #14
0
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     throw new NotSupportedException("Cannot select from multiple sources.");
     //base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     _namer.Add(fromClause);
 }
Пример #16
0
 /// <summary>
 /// Additional from clauses attached to the top here.
 /// </summary>
 /// <param name="fromClause"></param>
 /// <param name="queryModel"></param>
 /// <param name="index"></param>
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 {
     _qmContextStack.Peek().AddFromItem(fromClause);
     _exprVisitor.Visit(fromClause.FromExpression);
     base.VisitAdditionalFromClause(fromClause, queryModel, index);
 }
Пример #17
0
 /// <summary>
 ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
 ///     directly from your code. This API may change or be removed in future releases.
 /// </summary>
 public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
 => fromClause.TransformExpressions(TransformingVisitor.Visit);
Пример #18
0
        /// <inheritdoc />
        public override void VisitAdditionalFromClause(AdditionalFromClause fromClause, QueryModel queryModel, int index)
        {
            LogWriter.WriteLine($"VisitAdditionalFromClause {fromClause}");

            base.VisitAdditionalFromClause(fromClause, queryModel, index);
        }